Mybatis基础知识

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情:

    1. 封装JDBC操作
    1. 利用反射打通Java类与SQL语句之间的相互转换

MyBatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便,所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。

接口映射

在使用MyBatis的时候,都用的是Dao接口和XML文件里的SQL一一对应来进行使用的。那你是否思考过二者是如何建立关系的?

MyBatis会先解析这些XML文件,通过XML文件里面的命名空间(namespace)跟DAO建立关系;然后XML中的每段SQL会有一个id跟DAO中的接口进行关联。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略

通常一个Xml映射文件,都会写一个Dao接口与之对应。Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement。

如果配置了namespace,那么id是可以重复的,因为我们的Statement实际上就是namespace+id

举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。

#{}和${}的区别是什么?

  • #{}解析传递进来的参数数据
  • ${}对传递进来的参数原样拼接在SQL中
  • Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
    Mybatis 在处理 美元符号{} 时,就是把${}替换成变量的值
  • #{}是预编译处理,${}是字符串替换
  • 使用#{}可以有效的防止SQL注入,提高系统安全性。
select * from ${tableName} where name = #{name}
  在这个例子中,如果表名为

user; delete user; –

则动态解析之后 sql 如下:

select * from user; delete user; – where name = ?;
  --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。


    '#‘相当于对数据 加上 双引号,’$'相当于直接显示数据

    '#'将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。

    '$'将传入的数据直接显示生成在sql中。
  • #{} 用于CRUD语句
    ${} 则用于模糊查询(记得加%%哦),}一般用在order by, limit, group by等场所。

如何获取自动生成的(主)键值?

如果我们一般插入数据的话,如果我们想要知道刚刚插入的数据的主键是多少(一般这个主键是自增ID),一般情况下我们可能在以某个唯一字段与数据库进行一次查询交互,获取到自增id,但是这样相对比较麻烦,我们可以通过对mybatis进行配置。

    <insert id="insert" parameterType="com.qufenqi.pay.settlement.dao.po.SettleBasicData" useGeneratedKeys="true"
            keyProperty="id" keyColumn="id">
    insert into sett_basic_data (id, biz_order_no, biz_type, 
      fund_type, trade_mode, merchant_id, merchant_name, 
      create_time, update_time)
    values (#{id,jdbcType=BIGINT}, #{bizOrderNo,jdbcType=VARCHAR}, #{bizType,jdbcType=VARCHAR}, 
      #{fundType,jdbcType=VARCHAR}, #{tradeMode,jdbcType=VARCHAR}, #{merchantId,jdbcType=VARCHAR}, #{merchantName,jdbcType=VARCHAR},
      #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
  </insert>

在上述方法中添加useGeneratedKeys="true" keyProperty="id" keyColumn="id"
settleBasicDataMapper.insert(settleBasicData); settleBasicData.getId();
代码亲测有效

在mapper中如何传递多个参数?

  • 使用占位符的思想

    其中,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。

  • 采用Map传多参数 parameterType=“hashmap”

  • Dao层的函数方法,和占位符有些类似,目前单个参数用的主流方法(使用@Param注解)

  • 通过注解的方法查询(配合@Param注解)

  • 采用javaBean(一般应用于更新和查询情况)

    这种方法很直观,但需要建一个实体类,扩展不容易,需要加属性,看情况使用。

附带一个批量更新数据库的sql
对SettleBasicData集合中的每条数据进行更新

int updateBatch(@Param(value = "list") List<SettleBasicData> list);

    <update id="updateBatch" parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" open="" close="" separator=";">
            update sett_basic_data
            set
            status = #{item.status,jdbcType=VARCHAR},
            callback_status = #{item.callbackStatus,jdbcType=VARCHAR},
            update_time = #{item.updateTime,jdbcType=TIMESTAMP}
            where biz_order_no = #{item.bizOrderNo,jdbcType=VARCHAR}
            and biz_type = #{item.bizType,jdbcType=VARCHAR}
            and fund_type = #{item.fundType,jdbcType=VARCHAR}
        </foreach>
    </update>

在jdbc链接数据库时添加一下配置
?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true

亲手采过的坑。
这事因为原来mysql的批量更新是要我们主动去设置的, 就是在数据库的连接url上设置一下,加上* &allowMultiQueries=true *即可。

字段映射

将表中的字段与我们建立的entity实体进行建立关联

通过resultMap来映射字段名和实体类属性名的一一对应的关系

<select id="getOrder" parameterType="int" resultMap="orderresultmap">
        select * from orders where order_id=#{id}
</select>
 
//type对对应的实体类
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
  <!–用id属性来映射主键字段–>
  <id property=”id” column=”order_id”/>

  <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
  <result property = “orderno” column =”order_no”/>
  <result property=”price” column=”order_price” />
</reslutMap>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章