MyBatis增强

目录

 

1.使用步骤回顾

2.Log4j

3.Mapper(映射器接口)

1.employeeMapper.xml

2.EmployeeMapper

3.调用 Mapper的方法

4.MyBatis中动态sql

5.批量删除.添加.动态修改

5.1 批量删除

5.2 批量添加

5.3 动态修改

6.多对一

6.1 准备domain

6.2 嵌套结果

6.3 嵌套查询

7.一对多

7.1 准备domain

7.2 级连保存

7.3 嵌套结果

7.4 嵌套查询

8.缓存---->空间换时间


1.使用步骤回顾

  1. 导入相应的jar包---->9个
  2. Domain和数据库表
  3. Dao接口和实现
  4. DomainMapper.xml
  5. Mybatis-config.xml
  6. Dao实现完成,log4j
  7. 测试

  $:取值是直接的拼接,可能会出现sql的注入

   建议直接用#取值,是一个占位符

2.Log4j

   在项目中使用:

    ①:导入3个jar包

    ②:log4j.properties:

    ③:在需要使用的类中:

       a:创建一个logger:

        private  final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);

       b:使用:

          logger.info("info====");

          logger.trace("trace==");

          logger.warn("sfjislfjsd");

3.Mapper(映射器接口)

 和昨天相比:只定义dao的接口,不写实现:

     规范:以前的dao的包名:修改为mapper,接口名:UserMapper

    ①:规范:以前的dao的包名:修改为mapper,接口名:UserMapper

    ②:UserMapper.xml中:

       a:namespace必须和这个接口关联起来:就是接口的权限定名

       b:sql语句所在的标签的属性必须和接口的方法签名一致:

            sql是和接口的方法是对应的:

              方法名字和id一致;

              方法的参数和parameterType一致

              方法的返回值和resultType一致

       c:使用:

          通过SqlSession获取指定类的Mapper接口,然后调用你的方法:

            //api都是在sqlSession上:

            SqlSession sqlSession = MyBaitsUtil.getSqlSession();

            UserMapper mapper = sqlSession.getMapper(UserMapper.class);

            // org.apache.ibatis.binding.MapperProxy

            System.out.println(mapper);

            System.out.println(mapper.findOne(2L));

注意:

  1. 命名空间必须是接口的全限定名
  2. 方法名必须对应

例子:

  • 接口方法映射到对应的SQL
  • Mapper.xml的命名空间名称就是Maper接口的全限定名
  • Mapper接口上也可以写SQL(不建议这么做)

1.employeeMapper.xml

<!--这个命名空间的名称就是咱们Mapper接口的全限定名--><mapper namespace="cn.itsource._02_mapper.mapper.EmployeeMapper">

    <!--这个id的名称必需和映射的EmployeeMapper的方法名一致-->

    <insert id="save" parameterType="employee">

      ...

    </insert>

 

    <select id="findAll" resultType="employee">

      ...

</select></mapper>

2.EmployeeMapper

package cn.itsource._02_mapper.mapper;public interface EmployeeMapper {

 

    void save(Employee employee);//    @Select("select * from employee")

    List<Employee> findAll();

}

3.调用 Mapper的方法

SqlSession session = MyBatisUtil.openSession();

EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);

 

mapper.findAll().forEach(e -> System.out.println(e));

 

 

4.MyBatis中动态sql

   避免我们收到拼接sql语句,mybatis给我们搞定;

注意:

  • 准备一个Query对象(封装所有条件)
  • 模糊查询 concat("%",#{name},"%")
  • 遇到特殊符号 1.转义 < 2.CDATA段 <![CDATA[...]]>
  • 使用where标签(第一个and变成where)
  • if中有多个条件使用 and/or 进行关联
  • 如果出现相就的代码,可以单独抽取sql标签,引用include即可
  • Like------>模糊查询

<select id="findByQuery" parameterType="employeeQuery" resultType="employee">

        select * from employee <include refid="whereSql" /></select>

<!--准备代码片断--><sql id="whereSql">

    <where>

        <if test="name!=null and name!=''">

            and name like concat("%",#{name},"%")

        </if>

        <if test="minAge!=null">

            and age >= #{minAge}

        </if>

        <if test="maxAge!=null">

            <![CDATA[ and age<=#{maxAge} ]]>

        </if>

    </where></sql>

5.批量删除.添加.动态修改

5.1 批量删除

  • 首先知道sql delete from 表名 where id in (?,?,..)

collection="":代表你要循环的是什么? array/list
如果传过来的是数据,写array(集合就写list)
item:循环的每一个数据
open:拼接字符串以什么开始
close:拼接字符串以什么结尾
separator:拼接的时候每个值使用,隔开
index:遍历的下标

5.1.1 传数组的方法

 <delete id="batchDelete" parameterType="long[]">

        delete from employee where id in

        <foreach collection="array" item="v" open="(" close=")" separator=",">

            #{v}

        </foreach>

</delete>

5.1.2 传集合的方式

 <delete id="batchDelete" parameterType="list">

        delete from employee where id in

        <foreach collection="list" item="v" open="(" close=")" separator=",">

            #{v}

        </foreach>

    </delete>

5.2 批量添加

首先知道sql `insert into 表名 (p1,p2,...) values (#{p1},#{p2}),(#{p1},#{p2}),...

<insert id="batchSave" parameterType="list">

    insert into employee (name,age,sex) values

    <foreach collection="list" item="emp" separator=",">

        (#{emp.name},#{emp.age},#{emp.sex})

    </foreach>

</insert>

 

5.3 动态修改

咱们修改一个对象,咱们只能修改有数据的部分

<!--动态修改--><update id="update" parameterType="cn.itsource._02_mapper.domain.Employee">

    UPDATE employee

    <trim prefix="SET" suffixOverrides=",">

        <if test="name!=null and name!=''">

          name = #{name},

         </if>

        <if test="age!=null">

          age=#{age},

        </if>

        <if test="sex!=null">

          sex = #{sex}

        </if>

    </trim>

    WHERE id = #{id}</update>

更好的方案

<update id="update" parameterType="cn.itsource._02_mapper.domain.Employee">

    UPDATE employee

    <set>

        <if test="name!=null and name!=''">

            name = #{name},

        </if>

        <if test="age!=null">

            age=#{age},

        </if>

    </set>

    WHERE id=#{id}

</update>

 

6.多对一

         1:先封装基本属性: id  name

           主键使用id标签,其它使用result

           column="":表示的是数据库的列

           property="" 表示的是domain的属性

          2:再封装关联属性: department

           多对一:从多方入手,在这里封装的是一方

           association:就是表示封装的一个

           collection:就是表示封装的多个

               property="department":是domain中的哪一个属性封装

               javaType="cn.itsource.mybatis._05many2one.Department"  这个domain属性的类型

               column="deptId" :传递的参数

               select:发送的select的语句:namespace+.+id

  嵌套结果:只发送一条左外连接sql:

    已经把需要的字段全部查询出来,由于查询出来的列和domain的属性不一致,使用ResultMap解决;

          <!--01先封装基本属性-->

          <!--02再封装关联属性:多对一:处理的是一个-->

  • 准备(两张表employee,department,两个domain,两个mapper.xml)
  • 查询(嵌套结果[一条sql],嵌套查询[n+1条sql])

6.1 准备domain

6.1.1Employee

public class Employee {

 

    private Long id;

    private String name;

    private Integer age;

    private Boolean sex;

 

    private Department dept;

    //... getter,setter与toString

}

6.1.2Department

public class Department {

    private Long id;

    private String name;

    //... getter,setter与toString

}

6.2 嵌套结果

  • 查询的sql要关连多张表(一定要取别名,不然有些名称会产生冲突)
  • 当我们使用了association 后默认的映射失败,需要自己手动完成映射

<select id="findAll" resultMap="employeeMap">

    select e.id eid,e.name ename,e.age,e.sex,d.id did,d.name dname

      from employee e join department d on d.id = e.dept_id</select>

<resultMap id="employeeMap" type="employee">

    <!-- 手动完成基本映射 -->

    <id property="id" column="eid" />

    <result property="name" column="ename" />

    <result property="sex" column="sex" />

    <result property="age" column="age" />

    <!-- property:属性名,javaType:属性类型 -->

    <association property="dept" javaType="department">

        <id property="id" column="did" />

        <result property="name" column="dname" />

    </association></resultMap>

6.3 嵌套查询

  • 会产生n+1条sql
  • 需要去找到对应的那条sql并且执行
  • 保证MyBatis能找到这两个xml

employeeMapper.xml

<select id="findAll" resultMap="employeeMap">

    SELECT * FROM employee</select><!--嵌套查询方案--><resultMap id="employeeMap" type="employee">

    <id property="id" column="id" />

    <result property="name" column="name" />

    <result property="sex" column="sex" />

    <result property="age" column="age" /><!--

    查询相应的部门

        column:数据库对应的列 select:查询对应的sql的路径

 -->

    <association property="dept" javaType="department"

             column="dept_id" select="cn.itsource._04_many2one.DepartmentMapper.findById" /></resultMap>

departmentMapper.xml

<mapper namespace="cn.itsource._04_many2one.DepartmentMapper">

    <select id="findById" parameterType="long" resultType="department">

        select * from department where id = #{id}

    </select>

</mapper>

 

7.一对多

    嵌套查询和嵌套结果:

     使用整体上和多对一样的,区别在使用association这个地方换成collection.

7.1 准备domain

7.1.1Employee

public class Employee {

 

    private Long id;

    private String name;

    private Integer age;

    private Boolean sex;

     //... getter,setter与toString

}

7.1.2Department

public class Department {

    private Long id;

    private String name;

 

    private List<Employee> employees = new ArrayList<>();

7.2 级连保存

  • 准备两个Mapper
  • 保存部门后需要马上拿到它的id
  • 保存员工传的是Map{List<Employee>,deptId}

7.2.1departmentMapper.xml

<!--保存后需要拿到id--><insert id="save" parameterType="department"

        useGeneratedKeys="true" keyProperty="id" keyColumn="id">

    insert into department (name) values (#{name})</insert>

7.2.2employeeMapper.xml

<insert id="batchSave" parameterType="map">

    insert into employee (name,age,sex,dept_id) values

    <foreach collection="list" item="emp" separator=",">

        (#{emp.name},#{emp.age},#{emp.sex},#{deptId})

    </foreach>

</insert>

7.3 嵌套结果

  • 查询的sql要关连多张表(一定要取别名,不然有些名称会产生冲突)
  • 当我们使用了collection 后默认的映射失败,需要自己手动完成映射

<resultMap id="departmentMap" type="department">

    <id property="id" column="did" />

    <result property="name" column="dname" />

    <collection property="employees" ofType="employee">

        <id property="id" column="eid" />

        <result property="name" column="ename" />

        <result property="age" column="age" />

        <result property="sex" column="sex" />

    </collection>

</resultMap>

 

<select id="findAll" resultMap="departmentMap">

    select d.id did,d.name dname,e.id eid,e.name ename,e.age,e.sex

    from department d left join employee e on e.dept_id = d.id

</select>

7.4 嵌套查询

依赖需要找到对应的SQL

7.4.1departmentMapper.xml

<resultMap id="departmentMap" type="department">

    <id property="id" column="id" />

    <result property="name" column="name" />

    <collection property="employees" ofType="employee" column="id" select="cn.itsource._05_one2many.EmployeeMapper.findByDeptId">

    </collection>

</resultMap>

<select id="findAll" resultMap="departmentMap">

    select *  from department

</select>

7.4.2employeeMapper.xml

<!--这个命名空间的名称就是咱们Mapper接口的全限定名--><mapper namespace="cn.itsource._05_one2many.EmployeeMapper">

 

    //...

    

    <select id="findByDeptId" resultType="employee" parameterType="long">

        select * from employee where dept_id = #{deptId}

    </select>

</mapper>

 

8.缓存---->空间换时间

  Jpa:一级缓存和二级缓存

   EntityManager   EntityManagerFactory

mybatis:一级缓存(默认开启的)和二级缓存(需要配置)

   SqlSession      SqlSessionFactory

  • 自带一级级联
  • 二级缓存需要加上标签 <cache />
  • 二级缓存的对象必需是序列化对象 .. implements Serializable
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值