mybatis_基础

1 #和$的区别

#{}表示一个占位符号

  • 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,
  • #{}可以有效防止 sql 注入。
  • #{}可以接收简单类型值或 pojo 属性值。
  • 可以自动对值添加 ’ ’ 单引号

 

${}表示拼接 sql 串

  • 通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,
  • ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。
  • 比如order by id  这种的,以id排序  那么这个id 是没有单引号的,就是简单的SQL拼接,所以我们应该使用${} 而不是#{}
  • 当我们有多个变量的时候,我们就需要通过arg0,arg1来获取对应的变量了
    // 接口方法
    int updateNickname( int id,String nickname);
    <update id="updateNickname">
      # 读取第二个变量nickname和第一个变量id
      update t_user set nickname = #{arg1} where id = #{arg0}
    </update>
    
    // 接口方法
     int updateNickname( @Param("id") int id,@Param("nickname")String nickname);
        <update id="updateNickname">
            update t_user set nickname = #{nickname} where id = #{id}
        </update>
    

    包装类型单个参数

  • java有八个基本数据类型,我们在使用这些基本数据类型,可以直接取到对应的value,比如我们上次课程中涉及到的int类型。

    但是当我们的参数是包装类型时,比如String或者是User的实体类,这时mybatis就或读取包装类型中的属性,比如我们在使用User实体类时,直接使用实体类中的#{id}属性。但是String类型并没有对应的属性,我们希望的是直接获取String中的值,那么我们在取值的时候,就会出现这个错误。

  • 这个报错的意思就是从String类型中获取不到xxx属性

    这个使用我们也需要通过@Param的注解来解决这个问题

    // 接口方法
    List<User> selectList(@Param("orderBy") String orderBy);
    <select id="selectList" parameterType="String" resultType="User">
    	select * from t_user ${orderBy}
    </select>
    

    小结:

    一般我们获取变量值的时候使用#{}来读取属性,如果需要进行sql拼接的时候可以使用${},使用${}的时候要注意防止sql注入。

2 paramerterType 和 resultType

2.2 resultType

resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。

它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。

没有注册过的必须使用全限定类名。

实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。

4.3 resultMap

通过resultMap,我们可以指定查询结果字段和实体属性字段的映射关系

<resultMap id="userResult" type="User">
    <id column="id" property="id" />
    <result property="nickname" column="nickname" />
    <result property="schoolName" column="school_name" />
</resultMap>

3 mybatis-config.xml 配置文件

3.1 属性配置的两种方式

3.1.1 直接配置属性

<properties> 
  <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> 
  <property name="jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
  <property name="jdbc.username" value="root"/> 
  <property name="jdbc.password" value="root"/> 
</properties>

3.1.2 读取配置文件

创建db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/erp16?useUnicode=true&characterEncoding=UTF-8
username=root
password=root

配置文件读取

<properties resource="db.properties" />

3.2 typeAliases属性

<typeAliases> 
  <!-- 单个别名定义 --> 
  <typeAlias alias="user" type="com.tledu.zrz.pojo.User"/> 
  <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> 
  <package name="com.tledu.zrz.pojo"/> 
  <package name="其它包"/> 
</typeAliases>

3.3 mapper属性

Mappers是我们所说的映射器,用于通过mybatis配置文件去找到对应的mapper文件,关于这个属性有三种用法。

3.3.1 Resource

使用相对于类路径的资源如:<mapper resource="com/tledu/zrz/dao/IUserDao.xml" />

3.3.2 class

使用 mapper 接口类路径

如:<mapper class="com.tledu.zrz.dao.UserDao"/>

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

3.3.3 package

注册指定包下的所有 mapper 接口

如:<package name="com.tledu.zrz.mapper"/>

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中,并且这里如果希望能够扫描到包下面的xml文件的话,需要在maven中进行配置。

4 动态sql

4.1 if

<select id="list" parameterType="User" resultMap="userResult">
        select  * from t_user where 1=1
        <if test="username != null and username != ''">
            and username = #{username}
        </if>
        <if test="nickname != null and nickname != ''">
            and nickname like concat('%',#{nickname},'%')
        </if>
</select>

4.2 choose、when、otherwise

<select id="list" parameterType="User" resultMap="userResult">
        select * from t_user where 1=1
        <choose>
            <when test="id != null">
                and id = #{id}
            </when>
            <when test="username != null and username != ''">
                and username = #{username}
            </when>
            <otherwise>
                and nickname = #{nickname}
            </otherwise>
        </choose>
    </select>

4.3 where

 <select id="list" parameterType="User" resultMap="userResult">
        select * from t_user where 
        <where>
            <if test="username != null and username != ''">
                and username = #{username}
            </if>
            <if test="nickname != null and nickname != ''">
                and nickname like concat('%',#{nickname},'%')
            </if>
        </where>
    </select>

4.4 set

  <update id="updateNickname">
        update t_user
        <set>
            <if test="nickname != null and nickname != ''">
                nickname = #{nickname},
            </if>
            <if test="username != null and username != ''">
                username = #{username},
            </if>
        </set>
        where id = #{id}
    </update>

4.5 foreach

批量插入

 <insert id="batchInsert">
        insert into t_user (username, password, nickname) VALUES
        <foreach collection="list" index="idx" item="item" separator=",">
            (#{item.username},#{item.password},#{item.nickname})
        </foreach>
    </insert>

in查询

<select id="list" parameterType="User" resultMap="userResult">
        select * from t_user
        <where>
            <if test="user.username != null and user.username != ''">
                and username = #{user.username}
            </if>
            <if test="user.nickname != null and user.nickname != ''">
                and nickname like concat('%',#{user.nickname},'%')
            </if>
            and id in
            <foreach collection="idList" item="item" separator="," open="(" close=")">
                #{item}
            </foreach>
        </where>
    </select>

属性说明

  • collection 需要遍历的列表
  • item 每一项的形参名
  • index 每一项索引名
  • separtor 分隔符
  • open 开始符号
  • close 关闭符号

 5 联查

在项目中,某些实体类之间肯定有关联关系,比如一对一,一对多等,在mybatis 中可以通过association和collection,来处理这些关联关系。

5.1 1对1

在实现1对1映射的时候,可以通过association属性进行设置。在这里有三种方式

在地址表中,每个地址对应有一个创建用户,每次查询地址的时候希望查询到创建用户的内容

5.1.1 使用select

 <resultMap id="address" type="Address">
        <id column="id" property="id" />
        <association property="user" column="user_id" javaType="User" select="com.tledu.erp.dao.IUser2Dao.selectById"/>
</resultMap>
  • property配置了实体类对应的属性
  • column配置了关联字段
  • select对应了IUser2Dao中的查询语句

在执行sql的过程中就会同时调用在IUserDao中定义的sql进行联查。

这种方式会执行两次sql语句,效率相对较低,同时还需要先在IUserDao中进行定义后才能使用,比较麻烦

5.1.2 直接进行联查,在association中配置映射字段

这里可以直接写联查,需要转换的字段可以在association中进行配置。

  <resultMap id="address" type="Address" autoMapping="true">
        <id column="id" property="id" />
        <association property="user" column="user_id" javaType="User" >
          	<id column="user_id" property="id" />
            <result column="school_name" property="schoolName" />
        </association>
    </resultMap>

    <select id="selectOne" resultMap="address">
        select * from t_address left join t_user tu on tu.id = t_address.user_id where t_address.id = #{id}
    </select>

autoType代表自动封装,如果不填写,则需要添加所有的对应关系。

这种方式的问题是,当association需要被多次引用的时候,就需要进行多次重复的配置,所以我们还有第三种方式,引用resultMap。

5.1.3 嵌套的resultType

<resultMap id="addressMap" type="Address" autoMapping="true">
        <id column="id" property="id"/>
        <association property="user" column="user_id" resultMap="userMap">
        </association>
    </resultMap>

    <resultMap id="userMap" type="User" autoMapping="true">
        <id column="user_id" property="id" />
        <result column="school_name" property="schoolName"/>
    </resultMap>

    <select id="selectOne" resultMap="addressMap">
        select t_address.id,
               addr,
               phone,
               postcode,
               user_id,
               username,
               password,
               nickname,
               age,
               sex,
               school_name
        from t_address
                 left join t_user tu on tu.id = t_address.user_id
        where t_address.id = #{id}
    </select>

通过这种方式,userMap就可以被多次引用了。

  1. 通过别名保证查询的每一个元素是唯一的,以防止出现错乱的情况
  2. mybatis官网提醒,需要设置id提高查询性能

5.1 1对多

对于address来说,一个地址对应一个创建用户,但是对于User来说,一个用户可能对应创建了多条地址信息,这种情况,在mybatis中就可以通过collections解决。

同样也是有三种方法

5.2.1 使用select

这里的用法和1对1的时候一致

在AddressDao中添加

   <select id="selectByUserId" resultType="Address">
      select * from t_address where user_id = #{userId}
    </select>

在UserDao中添加

  <resultMap id="userResult" type="User" autoMapping="true">
        <id column="id" property="id"/>
        <result property="nickname" column="nickname"/>
        <result property="schoolName" column="school_name"/>
        <collection property="addressList" column="id" autoMapping="true" select="com.tledu.erp.dao.IAddressDao.selectByUserId" >
        </collection>
    </resultMap>


    <select id="selectById" parameterType="int" resultMap="userResult">
        select *
        from t_user
        where id = #{id}
    </select>

5.2.2 直接进行联查,在collection中配置映射字段

这里可以直接写联查,需要转换的字段可以在collection中进行配置。

<resultMap id="userResult" type="User" autoMapping="true">
        <id column="id" property="id"/>
        <result property="nickname" column="nickname"/>
        <result property="schoolName" column="school_name"/>
        <collection property="addressList" column="phone" ofType="Address" autoMapping="true">
            <id column="address_id" property="id" />
        </collection>
    </resultMap>


    <select id="selectById" parameterType="int" resultMap="userResult">
        select tu.id,
               username,
               password,
               nickname,
               age,
               sex,
               school_name,
               ta.id as address_id,
               addr,
               phone,
               postcode,
               user_id
        from t_user tu
                 left join t_address ta on tu.id = ta.user_id
        where tu.id = #{id}
    </select>

autoMapping代表自动封装,如果不填写,则需要添加所有的对应关系。

这里需要配置ofType来指定返回值类型

这种方式的问题是,当collection需要被多次引用的时候,就需要进行多次重复的配置,所以我们还有第三种方式,引用resultMap。

5.1.3 嵌套的resultType

 <resultMap id="userResult" type="User" autoMapping="true">
        <!--        <id column="id" property="id"/>-->
        <result property="nickname" column="nickname"/>
        <result property="schoolName" column="school_name"/>
        <collection property="addressList" column="phone" ofType="Address" resultMap="addressResultMap" autoMapping="true">
        </collection>
    </resultMap>

    <resultMap id="addressResultMap" type="Address" autoMapping="true">
        <id column="address_id" property="id" />
    </resultMap>


    <select id="selectById" parameterType="int" resultMap="userResult">
        select tu.id,
               username,
               password,
               nickname,
               age,
               sex,
               school_name,
               ta.id as address_id,
               addr,
               phone,
               postcode,
               user_id
        from t_user tu
                 left join t_address ta on tu.id = ta.user_id
        where tu.id = #{id}
    </select>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值