Mybatis入门(下集)动态SQL语句、缓存和逆向工程(附全部测试代码)

MyBatis第二天

  1. 动态SQL语句

(1)     Xml方式

(2)     注解方式

  1. MyBatis的缓存
  2. MyBatis的关联查询
  3. MyBatis逆向工程

1.     动态SQL语句

1.1.  动态SQL是什么

就是相对与固定SQL。就是通过传入的参数不一样,可以组成不同结构的SQL语句. 这种根据参数的条件修改SQL结构的SQL语句,我们称为动态SQL语句.

 

1.2.  动态SQL有什么用

1.根据条件组装不同结构的SQL语句,可以提高SQL代码的重用性.

2.满足某些特定需求,如,条件判断查询

 

1.3.  基于XML的实现

1.3.1.  标签包括

<sql>  用于声明公有的SQL语句块.,在操作标签中使用<include>调用 [不建议用]

不建议的原因,会导致代码难以维护。

<if>  类似java if(){},用于判断

<foreach>:类似java的foreach循环,一般用户批量处理的SQL语句

<trim> :切割标签,主要用于切割关键字的头和尾的字符.新版的Mybatis使用的几率很少.

<set>:使用 set标签就是SQL语言的set关键字,可以在update 的时候set 关键字后面的,逗号可以自动忽略

<where>:使用where标签作为SQL语言的where关键字,好处如果where后面的条件都不成立,忽略where关键字.

<choose> <when> <otherwise> :  java的swithc case

1.3.2.  接口文件

package cn.zj.mybatis.mapper;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Param;

 

import cn.zj.mybatis.pojo.User;

 

public interface UserMapper {

   

    /**

     * 根据条件查询结果

     * @param user

     * @return

     */

    List<User> selectByCondition(User user);

   

    /**

     * 根据提交查询总数

     * @param user

     * @return

     */

    Long selectTotalByCondition(User user);

   

    /**

     * 修改用户

     * @param user

     * @return

     */

    int updateUserByNotNull(User user);

   

    /**

     * 批量删除用户

     * @param ids

     * @return

     */

    int deleteByIds(@Param("ids")Integer[] ids);

   

    /**

     * 批量插入

     * @param users

     * @return

     */

    int insertByBatch(@Param("users")List<User> users);

   

}

 

 

1.3.3.  映射文件

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--  mapper 配置 mybatis 表的映射

    namespache :命名空间(和对应映射的接口的 全限定名一样),通俗讲,当前映射文件的唯一标识

         全限定名 : 包名+接口名/类名

 -->

<mapper namespace="cn.zj.mybatis.mapper.UserMapper">

 

   

    <!-- sql片段 -->

    <sql id="condition_sql">

         <!-- where 标签 -->

         <where>

             <if test="name !=null">

                  name like  concat('%',#{name},'%')

             </if>

             <if test="password !=null">

                  and password = #{password}

             </if>

             <if test="age !=null">

                  and age = #{age}

             </if>

         </where>

        

    </sql>

   

    <!-- 多条件查询 -->

    <select id="selectByCondition" parameterType="cn.zj.mybatis.pojo.User" resultType="cn.zj.mybatis.pojo.User">

         select * from user

         <!-- 引入sql片段 -->

         <include refid="condition_sql"/>

    </select>

   

    <!-- 多条件查询总数 -->

    <select id="selectTotalByCondition" parameterType="cn.zj.mybatis.pojo.User" resultType="long">

         select count(*) from user

         <!-- where 标签 -->

         <include refid="condition_sql"/>

    </select>

   

    <!-- 修改用户信息(数据不为空的修改) -->

    <update id="updateUserByNotNull" parameterType="cn.zj.mybatis.pojo.User">

         update user

         <set>

             <if test="name !=null">

                  name = #{name},

             </if>

             <if test="password !=null">

                  password = #{password},

             </if>

             <if test="age !=null">

                  age = #{age},

             </if>

         </set>

         where id = #{id}

    </update>

   

    <!-- 批量删除 -->

    <delete id="deleteByIds" parameterType="integer">

         <!-- sql : delete from user where id in (1,2,3,4) -->

         delete from user where id in

        

         <!-- 动态sql语句值 foreach -->

        

         <foreach collection="ids" item="id" open="(" close=")" separator=",">

             #{id}

         </foreach>

    </delete>

   

    <!-- 批量插入 -->

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

         <!-- insert into user (name,password,age) values (xx,xx,xx),(xx1,xx1,xx1) -->

        

         insert into user (name,password,age) values

        

         <foreach collection="users" item="user" separator="," >

             (#{user.name},#{user.password},#{user.age})

         </foreach>

    </delete>

</mapper>

 

1.3.4.  测试代码

 

package cn.zj.mybatis.test;

 

import java.util.ArrayList;

import java.util.List;

 

import org.apache.ibatis.session.SqlSession;

import org.junit.Test;

 

import cn.zj.mybatis.mapper.UserMapper;

import cn.zj.mybatis.pojo.User;

import cn.zj.mybatis.util.MyBatisUtil;

 

public class UserMapperTest {

 

    @Test

    public void testSelectByCondition() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

 

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         User user = new User();

         // user.setAge(30);

         user.setName("哥");

         List<User> users = userMapper.selectByCondition(user);

         for (User user2 : users) {

             System.out.println(user2);

         }

        

         Long totalCount = userMapper.selectTotalByCondition(user);

         System.out.println(totalCount);

        

         //关闭sesison

         session.close();

    }

 

    @Test

    public void testInsert() throws Exception {

 

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

 

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

         User user1 = new User(null, "西门吹雪", "xmcx", 25);

         User user2 = new User(null, "东方不败", "dfbb", 30);

 

         List<User> users = new ArrayList<>();

        

         users.add(user1);

         users.add(user2);

         // 3. 执行UserMapper的批量插入方法

         int row = userMapper.insertByBatch(users);

         System.out.println(row);

        

        

         // 4.提交事务(MyBatis是手动提交事务)

         session.commit();

 

         // 5.关闭Session

         session.close();

    }

 

 

    @Test

    public void testUpdate() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         User user = new User(1, null, "xf", null);

         // 3.执行修改方法

         int row = userMapper.updateUserByNotNull(user);

         System.out.println(row);

         // 4.提交事务

         session.commit();

 

         // 5.关闭session

         session.close();

    }

 

    @Test

    public void testDelete() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         Integer[] ids = { 2, 3, 5 };

 

         // 3.执行修改方法

         int row = userMapper.deleteByIds(ids);

         System.out.println(row);

         // 4.提交事务

         session.commit();

 

         // 5.关闭session

         session.close();

    }

 

}

 

 

1.4.  基于注解方式实现

动态sql除了支持xml方式以外,还是支持使用纯注解的方式

主要一下四个注解+对应动态sql语句的类文件

  1. @SelectProvider  动态查询SQL语句对应注解
  2. 2.    @InsertProvider  动态插入SQL语句对应注解
  3. 3.    @UpdateProvider  动态修改SQL语句对应注解
  4. 4.    @DeleteProvider  动态删除SQL语句对应注解

 

1.4.1.  接口映射文件

package cn.zj.mybatis.mapper;

 

import java.util.List;

 

import org.apache.ibatis.annotations.DeleteProvider;

import org.apache.ibatis.annotations.InsertProvider;

import org.apache.ibatis.annotations.Param;

import org.apache.ibatis.annotations.SelectProvider;

import org.apache.ibatis.annotations.UpdateProvider;

 

import cn.zj.mybatis.pojo.User;

import cn.zj.mybatis.pojo.UserProvider;

 

public interface UserMapper {

   

   

    /*

     * @SelectProvider(type=UserProvider.class,method="")

     * @SelectProvider 查询动态sql语句的 注解

     * type : 编写动态sql语句的类对应的字节码

     * method : 编写动态sql语句类对应的方法名称

     *   此方法返回的是一个String字符串,字符串就是拼接sql语句

     */

    @SelectProvider(type=UserProvider.class,method="selectByCondition")

    List<User> selectByCondition(User user);

   

    /**

     * 根据条件查询总数

     * @param user

     * @return

     */

    @SelectProvider(type=UserProvider.class,method="selectTotalByCondition")

    Long selectTotalByCondition(User user);

   

   

    /**

     * 修改用户信息,参数不为空的数据才会修改

     * @param user

     * @return

     */

    @UpdateProvider(type=UserProvider.class,method="updateByNotNull")

    int updateByNotNull(User user);

   

   

    /**

     * 批量删除

     * @param ids

     * @return

     */

    @DeleteProvider(type=UserProvider.class,method="deleteByIds")

    int deleteByIds(@Param("ids")List<Integer> ids);

   

    /**

     * 批量插入

     * @param users

     * @return

     */

    @InsertProvider(type=UserProvider.class,method="batchInsert")

    int batchInsert(@Param("users")List<User> users);

}

 

 

1.4.2.  动态sql语句文件

package cn.zj.mybatis.pojo;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Param;

 

/*

 * UserMapper接口映射对应的动态SQL语句的的类

 */

public class UserProvider {

   

    /**

     * 返回条件查询对应的动态sql语句

     * @param user  条件参数

     * @return sql

     */

    public String selectByCondition(User user) {

         StringBuilder sb = new StringBuilder();

         sb.append("select * from user WHERE 1 = 1 ");

         //动态拼接SQL语句

         if(user.getName() !=null) {

             //使用OGNL表达式获取 对象属性的值

             sb.append("AND name like  concat('%',#{name},'%')");

         }

         if(user.getAge() !=null) {

             sb.append("AND age = #{age}");

         }

        

         return sb.toString();

    }

   

    public String selectTotalByCondition(User user) {

         StringBuilder sb = new StringBuilder();

         sb.append("select count(1) from user WHERE 1 = 1 ");

         //动态拼接SQL语句

         if(user.getName() !=null) {

             //使用OGNL表达式获取 对象属性的值

             sb.append("AND name like  concat('%',#{name},'%')");

         }

         if(user.getAge() !=null) {

             sb.append("AND age = #{age}");

         }

        

         return sb.toString();

    }

   

   

   

    public String updateByNotNull(User user) {

         StringBuilder sb = new StringBuilder();

         sb.append("update user set ");

        

         if(user.getName() !=null) {

             sb.append("name = #{name},");

         }

         if(user.getPassword() !=null) {

             sb.append("password = #{password},");

         }

         if(user.getAge() !=null) {

             sb.append("age = #{age},");

         }

         //删除最后一个多余的逗号

         sb.deleteCharAt(sb.length()-1);

        

         sb.append(" where id = #{id}");

        

         return sb.toString();

    }

   

   

    public String deleteByIds(@Param("ids")List<Integer> ids) {

         StringBuilder sb = new StringBuilder();

         //delete from user where id in (1,3,5,6);

         sb.append("delete from user where id in (");

        

         for (int i = 0; i < ids.size(); i++) {

             //使用OGNL 表达式获取集合的每一个数据  #{ids[0]} #{ids[1]} #{ids[2]}...

             sb.append("#{ids["+i+"]},");

         }

        

         //删除最后一个多余的逗号

         sb.deleteCharAt(sb.length()-1);

        

         sb.append(")");

         return sb.toString();

    }

   

    public String batchInsert(@Param("users")List<User> users) {

         StringBuilder sb = new StringBuilder();

//       insert into user (name,password,age) values

//           (xxx,x,xx),(xxx1,x1,xx1),(xxx2,x2,xx2),

         sb.append("insert into user (name,password,age) values ");

        

        for (int i = 0; i < users.size(); i++) {

             sb.append("(");

             //姓名

             sb.append("#{users["+i+"].name},");

             //密码

             sb.append("#{users["+i+"].password},");

             //年龄

             sb.append("#{users["+i+"].age}");

             sb.append("),");

         }

         //删除最后一个多余的逗号

         sb.deleteCharAt(sb.length()-1);

         System.out.println("SQL :"+sb.toString());

         return sb.toString();

    }

}

 

1.4.3.  测试代码

package cn.zj.mybatis.test;

 

import java.util.ArrayList;

import java.util.List;

 

import org.apache.ibatis.session.SqlSession;

import org.junit.Test;

 

import cn.zj.mybatis.mapper.UserMapper;

import cn.zj.mybatis.pojo.User;

import cn.zj.mybatis.util.MyBatisUtil;

 

public class UserMapperTest {

 

    @Test

    public void testSelectByCondition() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

 

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         User user = new User();

         // user.setAge(30);

         user.setName("哥");

         List<User> users = userMapper.selectByCondition(user);

         for (User user2 : users) {

             System.out.println(user2);

         }

// 查询总数

         Long totalCount = userMapper.selectTotalByCondition(conditionUser);

         System.out.println("totalCount:" + totalCount);

         // 关闭session

         session.close();

    }

 

    @Test

    public void testInsert() throws Exception {

 

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

 

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

         User user1 = new User(null, "西门吹雪", "xmcx", 25);

         User user2 = new User(null, "东方不败", "dfbb", 30);

 

         List<User> users = new ArrayList<>();

        

         users.add(user1);

         users.add(user2);

         // 3. 执行UserMapper的批量插入方法

         int row = userMapper.insertByBatch(users);

         System.out.println(row);

        

        

         // 4.提交事务(MyBatis是手动提交事务)

         session.commit();

 

         // 5.关闭Session

         session.close();

    }

 

    @Test

    public void testUpdate() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         User user = new User(5, null, "xf", null);

         // 3.执行修改方法

         int row = userMapper.updateUserByNotNull(user);

         System.out.println(row);

         // 4.提交事务

         session.commit();

 

         // 5.关闭session

         session.close();

    }

 

    @Test

    public void testDelete() throws Exception {

         // 1.创建SqlSession对象

         SqlSession session = MyBatisUtil.openSession();

         // 2.创建UserMapper接口的代理对象

         UserMapper userMapper = session.getMapper(UserMapper.class);

 

         Integer[] ids = { 2, 3, 5 };

 

         // 3.执行修改方法

         int row = userMapper.deleteByIds(ids);

         System.out.println(row);

         // 4.提交事务

         session.commit();

 

         // 5.关闭session

         session.close();

    }

}

 

2.     缓存

在Mybatis里面,所谓的缓存就是将已经查询过的记录放在内存的缓冲区或文件上,这样如果再次查询,可以通过配置的策略,命中已经查询过的记录.从而提高查询的效率.

缓存作用

提高查询的效率.

2.1.  一级缓存

Mybatis的缓存分为一级缓存\ 二级缓存

 

一级缓存:所谓的一级缓存就是会话(SqlSesion对象)级别的缓存,就是同一个会话,如果已经查询过的数据会保存一份在内存中,如果会话没有关闭,再次调用同样的方法查询,不会再查询数据库,而是直接从缓存中取出之前查询的数据.

 

一级缓存默认是打开的,而且是关闭不了的.

 

如何清空一级缓存.

1.关闭会话.close()

2.进行了操作(增删改),提交了commit();

3.手工清除缓存clearCache()

2.1.1.  测试代码

@Test

public void testselectAll() {

    // 1.创建SqlSession对象

    //SqlSesion对象默认就开启了一级缓存,将已经查询过的数据就缓存到SqlSession的缓存区域

    //在此会话中如果再次发送同样的请求,那么直接从缓存区域获取数据,不会再发送SQL语句了

   

    SqlSession session1 = MyBatisUtil.openSession();

    //SqlSession session2 = MyBatisUtil.openSession();

    // 2.创建UserMapper接口的代理对象

    UserMapper mapper1 = session1.getMapper(UserMapper.class);

   

    //UserMapper mapper2 = session2.getMapper(UserMapper.class);

    //3.执行查询方法

    List<User> users1 = mapper1.selectAll();

   

    //手动清理缓存

    session1.clearCache();

   

    List<User> users2 = mapper1.selectAll();

}

 

2.2.  二级缓存

一级缓存是SqlSession对象级别,在每一次会话中有效

 

二级缓存是 SqlSessionFactory级别,在整个应用都有效,可以在多个会话有效

MyBatis本身并没有实现二级缓存

 

二级缓存需要第三方缓存提供商的支持

Ehcache -第三方缓存(Hibernate框架默认就是支持)

 

学习地址

http://www.mybatis.org/ehcache-cache/

 

2.2.1.  下载ehcache

https://github.com/mybatis/ehcache-cache/releases

 

2.2.2.  配置开启二级缓存

MyBatis开启二级缓存新版本已经默认支持开启二级缓存.可以不改

<settings>

    <!-- 开启二级缓存 -->

    <setting name="cacheEnabled" value="true"/>

</settings>

 

 

2.2.3.  导入Ehcachejar包

 

 

2.2.4.  Ehcache依赖 slfj 日志框架,必须要导入slfj的两个jar包

 

 

2.2.5.  创建 ehcache.xml配置文件

Ehcache有自己的配置文件,在src下面创建ehcache.xml 配置文件

<ehcache>

    <!-- 缓存的磁盘位置 -->

    <diskStore path="D:/mybatis_cache"/>

    <!-- 默认的缓存策略: 如果开发者在某一个需要缓存的文件配置了自定义缓存,就不使用默认的,如果没有配置,就使用默认缓存策略-->

    <defaultCache

        maxElementsInMemory="10000"

        eternal="false"

        timeToIdleSeconds="120"

        timeToLiveSeconds="120"

        overflowToDisk="true"

      />

</ehcache>

 

在映射文件中配置<cache>以及配置对应的缓存策略

<mapper namespace="cn.zj.mybatis.dao.UserMapper">

   

    <!-- 当前表的映射开启支持二级缓存,并设置相关的缓存提供商,以及缓存的相关配置 -->

    <cache type="org.mybatis.caches.ehcache.EhcacheCache" >

       <!--最大的空闲时间  -->

       <property name="timeToIdleSeconds" value="10000"/>

       <!-- 最大的在线时间 -->

       <property name="timeToLiveSeconds" value="20000"/>

       <!-- 内存的大小 b字节 m1 =1024k 1k=1024b -->

       <property name="maxEntriesLocalHeap" value="2000000"/>

       <!-- 文件的大小 b字节-->

       <property name="maxEntriesLocalDisk" value="20000000"/>

       <!-- 算法 LRU:最少使用优先, "LFU" or "FIFO:先进先出 -->

       <property name="memoryStoreEvictionPolicy" value="LRU"/>

    </cache>

    <select id="selectAll" resultType="User">

         select * from user

    </select>

</mapper>

因为二级缓存可以缓存到文件(将对象序列化到本地),涉及到对象序列化,那么对应的javaBean对象就必须实现

public class User implements Serializable{

    private static final long serialVersionUID = -8366151150155170110L;

}

2.2.6.  缓存的命中率

命中率= 从缓存中获取数据的次数/ 查询的总次数

如 : 两次查询 从缓中获取一次

0.5 =  1/2;

0.666666 = 2/3;

命中率越高缓存效果越好

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.0

DEBUG [main] - ==>  Preparing: select * from user where id = ?

DEBUG [main] - ==> Parameters: 3(Integer)

DEBUG [main] - <==      Total: 1

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.5

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.6666666666666666

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.75

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8333333333333334

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8571428571428571

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.875

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8888888888888888

DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.9

3.     MyBatis的对象关系映射(难点重点)

在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值连接), 等值连接 表与表之间有一个外键关键

 

但是程序中最终获取的表封装的对象, 对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系

 

对象之间关系主要是四种

 

一对一关系
一个人对应身份证id,一个QQ号对应一个QQ空间

一对多关系

    一个部门对应多个员工

多对一关系

   多个员工对应一个部门

多对多关系

   多个学生对应多个老师,多个学生对应多个课程

什么关系应该从哪个对象作为中心点来看

一对多, 以one方作为中心点

 

MyBatis框架支持多表查询封装对象之间关系

 

<collection> 一对多查询

<association>多对一和一对一查询

 

3.1.  准备多表,表之间有外键关系(员工表和部门表)

员工表

CREATE TABLE `employee` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `name` varchar(50) DEFAULT NULL,

  `dept_id` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

部门表

CREATE TABLE `department` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `name` varchar(255) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

 

3.2.  多对一查询

public class Employee {

    private Integer id;

    private String name;

    //以员工为中心 :

                      多个员工对应一个部门,多对一关系,many2one

    //员工与部门的对象关系

    private Department dept;

 

    public Integer getId() {

         return id;

    }

 

    public void setId(Integer id) {

         this.id = id;

    }

 

    public String getName() {

         return name;

    }

 

    public void setName(String name) {

         this.name = name;

    }

 

    public Department getDept() {

         return dept;

    }

 

    public void setDept(Department dept) {

         this.dept = dept;

    }

 

    @Override

    public String toString() {

         return "Employee [id=" + id + ", name=" + name + ", dept=" + dept + "]";

    }

}

public class Department {

    private Integer id;

    private String name;

    public Integer getId() {

         return id;

    }

    public void setId(Integer id) {

         this.id = id;

    }

    public String getName() {

         return name;

    }

    public void setName(String name) {

         this.name = name;

    }

    @Override

    public String toString() {

         return "Department [id=" + id + ", name=" + name + "]";

    }

}

Man2oneMapper.xml 映射文件

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <!-- 映射配置

    namespace : 命名空间,通俗讲,每个映射文件唯一的标识名称

  -->

<mapper namespace="cn.zj.mybatis.mapper.Many2OneMapper">

 

 

    <select id="selectByEmpId" parameterType="Integer" resultMap="emp_map">

        

         select * from employee where id = #{id}

        

    </select>

   

   

    <resultMap type="cn.zj.mybatis.pojo.Employee" id="emp_map">

        

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

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

        

         <!--

             需要映射部门对象属性

             private Department dept;

            

            解决方案,使用关联查询

            <association property="dept" column="dept_id" select=""/>

              property :需要映射的属性

              column :要映射属性对应的外键列

              select :对应的查询方案, 对应查询的命名空间+.+功能id

          -->

         <association property="dept" column="dept_id"

         select="cn.zj.mybatis.mapper.Many2OneMapper.findDeptById"/>

        

    </resultMap>

   

    <!-- 根据部门Id查询对应的部门对象 -->

    <select id="findDeptById" parameterType="Integer" resultType="cn.zj.mybatis.pojo.Department">

         select * from department where id = #{dept_id}

    </select>

   

</mapper>

3.3.  一对多查询

以部门为中心查询部门的所有信息(包括员工),一个部门对应多个员工

 

Pojo对象

public class Department {

    private Integer id;

    private String name;

   

    //以部门为中心:一个部门对应多个与员工  一对多关系 (one2many)

    private List<Employee> emps;

   

    public Integer getId() {

         return id;

    }

    public void setId(Integer id) {

         this.id = id;

    }

    public String getName() {

         return name;

    }

    public void setName(String name) {

         this.name = name;

    }

    public List<Employee> getEmps() {

         return emps;

    }

    public void setEmps(List<Employee> emps) {

         this.emps = emps;

    }

    @Override

    public String toString() {

         return "Department [id=" + id + ", name=" + name + ", emps=" + emps + "]";

    }

}

public class Employee {

    private Integer id;

    private String name;

 

    public Integer getId() {

         return id;

    }

 

    public void setId(Integer id) {

         this.id = id;

    }

 

    public String getName() {

         return name;

    }

 

    public void setName(String name) {

         this.name = name;

    }

    @Override

    public String toString() {

         return "Employee [id=" + id + ", name=" + name + "]";

    }

}

3.3.1.  N+1方式

N+1 : N 就是当前需要查询结果对应发送的SQL语句的条数

       +1 关联查询数据需要额外多发一条SQL语句才能查询出对应的结果

3.3.1.1.     映射代码

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <!-- 映射配置

    namespace : 命名空间,通俗讲,每个映射文件唯一的标识名称

  -->

<mapper namespace="cn.zj.mybatis.mapper.One2ManyMapper">

    <select id="selectDeptById" parameterType="Integer" resultMap="dept_map">   

         select * from department where id = #{id}

    </select>

   

    <!-- 手动映射 -->

    <resultMap type="cn.zj.mybatis.pojo.Department" id="dept_map">

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

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

        

         <!-- private List<Employee> emps;

             集合属性映射

              <collection property="emps" column="id" select=""/>

                 property:需要映射得集合 emps

                 column : 部门的主键 id

                 select : 关联查询,去根据部门id查询出对应的员工

                           值关联查询功能的  命名空间+.+功能id

          -->

          <collection property="emps" column="id" select="cn.zj.mybatis.mapper.One2ManyMapper.selectUsersByDeptId"/>

   

    </resultMap>

   

   

    <!-- 关联查询的功能

         根据部门的id查询所有的员工

     -->

    <select id="selectUsersByDeptId" parameterType="integer" resultType="cn.zj.mybatis.pojo.Employee">

         select * from employee where dept_id = #{id}

    </select>

</mapper>

3.3.1.2.     运行结果

 

 

3.3.2.  等值连接查询

3.3.2.1.     映射代码

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <!-- 映射配置

    namespace : 命名空间,通俗讲,每个映射文件唯一的标识名称

  -->

<mapper namespace="cn.zj.mybatis.mapper.One2ManyMapper">

 

 

    <select id="selectDeptById" parameterType="Integer" resultMap="dept_map">

        

         select e.id e_id ,e.name e_name,d.id d_id,d.name d_name

    from department d JOIN employee e ON d.id = e.dept_id WHERE d.id = #{id};

        

    </select>

   

    <!-- 手动映射 -->

    <resultMap type="Department" id="dept_map">

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

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

        

         <!-- private List<Employee> emps;

             集合属性映射

              <collection property="emps" column="id" select=""/>

                 property:需要映射得集合 emps

                 column : 部门的主键 id

                 ofType : 需要映射集合的泛型的类型

          -->

          

          <collection property="emps" ofType="Employee">

             <!-- 集合泛型类型对应的pojo的主键列映射 ,Employee的主键列映射 -->

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

             <!-- 集合泛型类型对应的pojo的非主键列映射 ,Employee的非主键列映射 -->

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

          </collection>

   

    </resultMap>

   

</mapper>

3.3.2.2.     运行结果

只会发送一条SQL语句

DEBUG [main] - ==>  Preparing: select e.id e_id ,e.name e_name,d.id d_id,d.name d_name from department d JOIN employee e ON d.id = e.dept_id WHERE d.id = ?;

DEBUG [main] - ==> Parameters: 1(Integer)

DEBUG [main] - <==      Total: 2

Department [id=1, name=总经办, emps=[Employee [id=1, name=乔峰], Employee [id=3, name=段誉]]]

 

4.     MyBatis的逆向工程

MyBatis的逆向工程能自动帮开发者生成数据库表对应的 pojo实体文件,自动生成映射文件

自定生成表的各种(CRUD)的sql语句, 但是只能做单表操作,联合查询还得开发者自己动

 

使用逆向工程得先在Eclipse安装逆向工程的插件

4.1.  插件安装步骤

 
 
 

 

判断是否安装成功

 

 

 

 

 

 

4.2.  逆向工程步骤

4.2.1.  新建一个普通java项目,导入mybatis.jar包和数据库驱动包

 

 

 

4.2.2.  生成配置文件

 

 

 

 

 

 

 

配置生成文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

  <context id="context1">

   <!-- 注释构建 -->

    <commentGenerator>

       <!-- 去掉所有的注释 -->

    <property name="suppressAllComments" value="true"/>

    <property name="suppressDate" value="true"/>

    </commentGenerator>

   

    <!-- 数据库四要素 -->

    <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/mybatis"

    driverClass="com.mysql.jdbc.Driver"

    password="admin"

    userId="root" />

    <!-- 实体类 : pojo

    targetPackage : 实体类生成后存放的包

    targetProject : 存放的目录一般都放在 src下面

      -->

    <javaModelGenerator targetPackage="cn.zj.mybatis.pojo" targetProject="mybatis-generator/src" />

    <!-- 映射文件 -->

    <sqlMapGenerator targetPackage="cn.zj.mybatis.mapper" targetProject="mybatis-generator/src" />

    <!-- 操作接口

    type 生成映射的形式

         ANNOTATEDMAPPER : 纯注解的,没有xml映射

         XMLMAPPER : 生成的有xml映射文件

    -->

    <javaClientGenerator  targetPackage="cn.zj.mybatis.mapper" targetProject="mybatis-generator/src" type="XMLMAPPER" />

   

    <!-- 要生成对应表的配置

    tableName : 数据库表名

    //如果下面全部是true,mybatis直接可以使用纯面向对象开发

    enableCountByExample : 是否生成查询总数的 Example

    enableDeleteByExample : 是否生成删除的 Example

    enableSelectByExample : 是否生成查询集合的 Example

    enableUpdateByExample : 是否生成修改的 Example

     -->

    <table  tableName="user"  enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>

    <table  tableName="employee" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>

    <table  tableName="department" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="true" enableUpdateByExample="false"></table>

  </context>

</generatorConfiguration>

 

 

4.2.3.  开始逆向工程

选中 generatorConfig.xml 逆向工程配置文件,点击鼠标右键

 

posted @ 2019-06-10 20:18  沈振辉  阅读(430)  评论(0编辑  收藏  举报