Mybatis从入门到放弃(三)

十四、Mybatis的逆向工程

        (一)逆向工程介绍

                Mybatis的一个主要的特点就是需要程序员自己编写sql,但是如果表太多的话难免会很麻烦,所以Mybatis官方提供了一个逆向工程,可以针对单表自动生成mybatis执行所需的代码。

        (二)构建项目环境

                1、构建maven工程并导入依赖

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-core</artifactId>
        <version>1.3.7</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.16</version>
    </dependency>
</dependencies>

                2、编写配置框架配置文件

?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<properties resource="db.properties"></properties>
<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
    <package name="cn.offcn.entity"></package>
</typeAliases>
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<environments default="development">
<environment id="development">
    <transactionManager type="JDBC"></transactionManager>
    <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </dataSource>
</environment>
</environments>
<!--在核心配置文件中注册mapper-->
<mappers>
    <package name="cn.offcn.mapper"></package>
</mappers>
</configuration>

                3、编写逆向工程的配置文件generator.xml

<?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="testTables" targetRuntime="MyBatis3">
    <!--实体类实现序列化接口-->
    <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
    <!--生成实体类中的toString方法-->
    <plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/mybatis828_002"userId="root" password="root">
        </jdbcConnection>

<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时
把JDBC DECIMAL 和NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

    <!-- targetProject:生成实体类的位置 -->
    <javaModelGenerator targetPackage="cn.offcn.entity"
        targetProject=".\src\main\java">
        <!-- enableSubPackages:是否让schema作为包的后缀 -->
        <property name="enableSubPackages" value="false" />
        <!-- 从数据库返回的值被清理前后的空格 -->
        <property name="trimStrings" value="true" />
    </javaModelGenerator>

    <!-- targetProject:mapper映射文件生成的位置 -->
    <sqlMapGenerator targetPackage="cn.offcn.mapper"targetProject=".\src\main\resources">
        <!-- enableSubPackages:是否让schema作为包的后缀 -->
        <property name="enableSubPackages" value="false" />
    </sqlMapGenerator>
    <!-- targetPackage:mapper接口生成的位置 -->
    <javaClientGenerator type="XMLMAPPER"targetPackage="cn.offcn.mapper"
targetProject=".\src\main\java">
        <!-- enableSubPackages:是否让schema作为包的后缀 -->
        <property name="enableSubPackages" value="false" />
    </javaClientGenerator>
    <!-- 指定数据库表 -->
    <table tableName="department"></table>
    <table tableName="employee"></table>
    <table tableName="person"></table>
    <table tableName="idcard"></table>
    <table tableName="student"></table>
    <table tableName="teacher_student"></table>
    <table tableName="teacher"></table>
    </context>
</generatorConfiguration>

                4、调用官方api实现逆向工程

package cn.test;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class GeneratorTest {

public static void main(String[] args) throws Exception{
    List<String> warnings = new ArrayList<String>();
    boolean overwrite = true;
    //指定 逆向工程配置文件
    File configFile = new
File("F:\\828class\\workspace\\mybatis\\mybatis004_reflect\\generatorConfig.
xml");
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callba ck = new DefaultShellCallback(overwrite);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,callback, warnings);
    myBatisGenerator.generate(null);
    }
}

                5、使用逆向工程完成数据CRUD

//添加员工
public static void addEmployee(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    Employee employee=new Employee();
    employee.seteName("马大力");
    employee.seteGender("男");
    employee.seteAge(23);
    employee.seteDepartId(1);
    employeeMapper.insert(employee);
    session.commit();
    MyBatisUtils.close(session);
}

//根据id查询员工
public static void queryEmployeeById(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    Employee emp=employeeMapper.selectByPrimaryKey(2);
    System.out.println(emp);
    session.commit();
    MyBatisUtils.close(session);
}

//根据年龄查询员工
public static void queryEmployeeByAge(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    EmployeeExample employeeExample=new EmployeeExample();
    EmployeeExample.Criteria criteria=employeeExample.createCriteria();
    criteria.andEAgeGreaterThan(20);
    List<Employee> employeeList=employeeMapper.selectByExample(employeeExample);
    for (Employee employee : employeeList) {
        System.out.println(employee);
    }
    session.commit();
    MyBatisUtils.close(session);
}

//根据年龄和性别查询员工
public static void queryEmployeeByAgeAndGender(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    EmployeeExample employeeExample=new EmployeeExample();
    EmployeeExample.Criteria criteria=employeeExample.createCriteria();
    criteria.andEAgeGreaterThan(20);
    criteria.andEGenderEqualTo("男");
    List<Employee> employeeList=employeeMapper.selectByExample(employeeExample);
    for (Employee employee : employeeList) {
        System.out.println(employee);
    }
    session.commit();
    MyBatisUtils.close(session);
}

//根据id修改员工
public static void updateEmployeeById(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    Employee employee= employeeMapper.selectByPrimaryKey(1);
    employee.seteGender("女");
    employee.seteDepartId(2);
    employeeMapper.updateByPrimaryKey(employee);
    session.commit();
    MyBatisUtils.close(session);
}

//根据id删除员工
public static void deleteEmployeeById(){
    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    employeeMapper.deleteByPrimaryKey(10);
    session.commit();
    MyBatisUtils.close(session);
}

//根据姓名更新员工
public static void updateEmployeeByName(){
    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    Employee employee= employeeMapper.selectByPrimaryKey(1);
    employee.seteGender("男");
    employee.seteAge(24);
    EmployeeExample employeeExample=new EmployeeExample();
    EmployeeExample.Criteria criteria = employeeExample.createCriteria();
    criteria.andENameEqualTo(employee.geteName());
    employeeMapper.updateByExample(employee,employeeExample);
    session.commit();
    MyBatisUtils.close(session);
}

//根据性别和部门查询员工
public static void queryEmployeeByGenderNum(){
    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    EmployeeExample employeeExample=new EmployeeExample();
    EmployeeExample.Criteria criteria = employeeExample.createCriteria();
    criteria.andEGenderEqualTo("男");
    criteria.andEDepartIdEqualTo(1);
    long count= employeeMapper.countByExample(employeeExample);
    System.out.println(count);
    session.commit();
    MyBatisUtils.close(session);
}

//根据部门查询员工
public static Employee queryEmployeeDepartmentById(int eid){
    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    Employee employee=employeeMapper.selectByPrimaryKey(eid);
    //查部门
    DepartmentMapper departmentMapper=session.getMapper(DepartmentMapper.class);
    Department department=departmentMapper.selectByPrimaryKey(employee.geteDepartId());
    employee.setDepart(department);
    session.commit();
    MyBatisUtils.close(session);
    return employee;
}

public static void main(String[] args) {
    addEmployee();
    queryEmployeeById();
    queryEmployeeByAge();

    queryEmployeeByAgeAndGender();

    updateEmployeeById();
    updateEmployeeByName();
    deleteEmployeeById();

    queryEmployees();
    queryEmployeeByGenderNum();
    Employee employee=queryEmployeeDepartmentById(1);
    System.out.println(employee.geteName()+"\t"+employee.getDepart().getdName());
    queryEmployees(1,2);
}

十五、Mybatis缓存

(一)缓存简介

缓存是存在于内存中的临时数据,使用缓存的目的是减少和数据库的交互次数,提高执行效率。像大多数的持久化框架一样,Mybatis也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis中缓存分为一级缓存、二级缓存。

(二)一级缓存

        1、一级缓存介绍

        mybatis一级缓存是一种session级别的,针对同一会话SqlSession中,执行多次条件完全相同的同一个sql,那么会共享这一缓存

        2、一级缓存结构图

                        

        3、编写用户持久层Dao层

public interface EmployeeDao {

    public Employee getEmployeeById(int id);
}

        4、编写用户持久层映射文件

<select id="getEmployeeById" resultMap="EmployeeResultMap">
    SELECT * FROM employee WHERE e_id=#{id}
</select>
<resultMap id="EmployeeResultMap" type="Employee">
    <id column="e_id" property="id"></id>
    <result column="e_name" property="name"></result>
    <result column="e_gender" property="gender"></result>
    <result column="e_age" property="age"></result>
</resultMap>

        5、编写测试方法

public static void firstCahce(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);

    //第一次查询
    Employee employee1=employeeMapper.getEmployeeById(1);
    System.out.println(employee1.getName());

    //第二次查询
    Employee employee2=employeeMapper.getEmployeeById(1);
    System.out.println(employee2.getName());
    MyBatisUtils.close(session);
}

结果:

                

        6、一级缓存分析

                从上面的代码可以看出,我们写了两次查询操作,但在访问数据时,只有一次。第一次先从一级缓存中获取,因为session是新创建的,一级缓存中没有数据,于是就查询数据获取数据,然后把查询的数据放到一级缓存中,此时一定要注意,一级缓存是一个Map集合,map的key是你的查询条件字符串,值就是查询出来的对象。

                第二次查询时,先从一级缓存中获取,因为上一次查询后已经放到一级缓存中,所以从一级缓存中获取到了,就不用访问数据库,减少了和数据库的一次交互,提高了执行效率。

        7、测试一级缓存的清空

                当我们在两次查询之间做增、删、改操作都会把一级缓存清空,因为不清空就不能保证缓存中的数据与数据库中数据的一致性,可能会读取不正确的数据。

                

public static void firstCahce(){

    SqlSession session = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper=session.getMapper(EmployeeMapper.class);
    //第一次查询
    Employee employee1=employeeMapper.getEmployeeById(1);
    System.out.println(employee1.getName());
    //新增员工
    employeeMapper.addEmployee(new Employee("张小志","男",18));
    //第二次查询
    Employee employee2=employeeMapper.getEmployeeById(1);
    System.out.println(employee2.getName());
    MyBatisUtils.close(session);
}

(三)二级缓存

        1、二级缓存简介

        二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的Sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

        2、二级缓存结构图

                        

        3、二级缓存的开启与关闭

             (1)在SqlMapConfig.xml文件开启二级缓存

<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>

             (2)配置相关的Mapper映射文件

<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.offcn.dao.EmployeeDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>

             (3)配置statement上面的useCache属性

<select id="getEmployeeById" resultMap="EmployeeResultMap" useCache="true">
    SELECT * FROM employee WHERE e_id=#{id}
</select>
<resultMap id="EmployeeResultMap" type="Employee">
    <id column="e_id" property="id"></id>
    <result column="e_name" property="name"></result>
    <result column="e_gender" property="gender"></result>
    <result column="e_age" property="age"></result>
</resultMap>

将EmployeeDao.xml映射文件中的<select>标签中设置useCache="true"代表当前这个statement要使用二级缓存,如果不使用二级缓存可以设置为false。

             (4)二级缓存测试

public static void secondCahce(){

    SqlSession session1 = MyBatisUtils.getSession();
    SqlSession session2 = MyBatisUtils.getSession();
    EmployeeMapper employeeMapper1=session1.getMapper(EmployeeMapper.class);
    //第一次查询
    Employee employee1=employeeMapper1.getEmployeeById(1);
    System.out.println(employee1.getName());
    session1.commit();
    MyBatisUtils.close(session1);
    //第二次查询
    EmployeeMapper employeeMapper2=session2.getMapper(EmployeeMapper.class);
    Employee employee2=employeeMapper2.getEmployeeById(1);
    System.out.println(employee2.getName());
    session2.commit();
    MyBatisUtils.close(session2);
}

经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二次查询时,我们发现没有对数据库发出sql语句,所以此时的数据就只能是来自于我们所说的二级缓存。

十六、Mybatis分页插件

(一)分页插件的介绍

        分页是一种将所有数据分段展示给用户的技术,用户每次看到的不是全部数据,而是其中一部分。如果在其中没有找到自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止。

(二)分页插件的引入和配置

//1.在pom.xml中引入插件依赖
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

//2.在mybatis核心配置文件中进行配置
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

(三)定义接口方法getInfo

public class EmployeeDao{
    public void getInfo();
}

(四)配置sql语句对于接口方法

<select id="getInfo" resultType="cn.offcn.entity.Employee">
    SELECT * FROM employee
</select>

(五)测试分页插件作用

@Test
public void queryEmployees(){
    //在查询前设置当前页与每页显示的记录数
    PageHelper.startPage(1,5);
    SqlSession session = MyBatisUtils.getSession();
    EmployeeDao employeeDao=session.getMapper(EmployeeDao.class);
    //查询
    List<Employee> employeeList=employeeDao.getInfo();
    //创建一个PageInfo对象,把查询出的结果集合当做参数传入
    PageInfo<Employee> pageInfo=new PageInfo<>(employeeList);
    List<Employee> empList=pageInfo.getList(); //取当前页的所有记录
    long totalRecored=pageInfo.getTotal();//总记录数
    int totalPages=pageInfo.getPages(); //总页数
    System.out.println("总记录数:"+totalRecored);
    System.out.println("总页数:"+totalPages);
    for (Employee employee : empList) {
    System.out.println(employee);
    }
    session.commit();
    MyBatisUtils.close(session);
}

十七、Mybatis的注解开发

(一)注解开发的背景介绍

        注解提供了一种简单的方式来实现简单映射渔具,而不会引入大量开销。特别是框架相关代码,本来可能需要很多配置文件,需要很多逻辑才能实现的内容,就可以使用一个或者多个注解来代替,这样就使得变成更加简洁。

(二)常用注解介绍

@Insert 实现新增
@Update 实现更新
@Delete 实现删除
@Select 实现查询

@Result

实现结果集封装
@Results 可以与@Result一起使用,封装多个结果集
@ResultMap 实现引用@Results定义的封装
@One 实现一对一结果集封装
@Many 实现一对多结果集封装
@SelectProvider 实现动态SQL映射

(三)项目环境搭建

        构建maven工程,导入依赖

<dependencies>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
</dependencies>

(四)使用Mybatis注解实现基本CRUD

        1、编写实体类

public class Worker {
private Integer id;
private String name;
private String gender;
private Integer age;
public Worker(){}
public Worker(String name, String gender, Integer age) {
this.name = name;
this.gender = gender;
this.age = age;
}

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 String getGender() {
    return gender;
}

public void setGender(String gender) {
    this.gender = gender;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

@Override
public String toString() {
    return "Worker{" +
        "id=" + id +
        ", name='" + name + '\'' +
        ", gender='" + gender + '\'' +
        ", age=" + age +
        '}';
    }
}

        2、使用注解方式开发持久层接口

public interface WorkerMapper {

@Insert("insert into worker (w_name,w_gender,w_age) " + "values(#{name},#{gender},#{age})")
public void saveWorker(Worker worker);

@Update("update worker set w_name=#{name},w_gender=#{gender},w_age=#{age} where w_id=#{id}")
public void updateWorker(Worker worker);

@Delete("delete from worker where w_id=#{id}")
public void deleteWorkerById(Integer id);

@Select("select * from worker where w_id=#{id}")
@Results({
    @Result(column = "w_id",property="id"),
    @Result(column = "w_name",property="name"),
    @Result(column = "w_gender",property="gender"),
    @Result(column = "w_age",property="age")
})
public Worker getWorkerById(Integer id);

@Select("select * from worker")
@Results({
    @Result(column = "w_id",property="id"),
    @Result(column = "w_name",property="name"),
    @Result(column = "w_gender",property="gender"),
    @Result(column = "w_age",property="age")
})
public List<Worker> getWorkers();
}

        3、编写SqlMapConfig配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置 mybatis的环境 -->
<environments default="development">
<!-- 配置环境 -->
<environment id="development">
    <!-- 配置事务的类型 -->
    <transactionManager type="JDBC"></transactionManager>
    <!-- 配置连接数据库的信息:用的是数据源【连接池】-->
    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis002"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </dataSource>
</environment>
</environments>
<mappers>
<package name="cn.offcn.dao"></package>
</mappers>
</configuration>

        4、编写测试方法

import cn.offcn.dao.WorkerMapper;
import cn.offcn.entity.Worker;
import cn.offcn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;

public class WorkerTest {

@Test
public void testSaveWorker(){

    SqlSession session = MyBatisUtils.getSession();
    WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
    Worker worker=new Worker("白晓云","女",20);
    workerMapper.saveWorker(worker);
    session.commit();
    MyBatisUtils.close(session);
}

@Test
public void testUpdateWorker(){

    SqlSession session = MyBatisUtils.getSession();
    WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
    Worker worker=new Worker(1,"白晓云","男",22);
    workerMapper.updateWorker(worker);
    session.commit();
    MyBatisUtils.close(session);
}

@Test
public void testDeleteWorkerById(){

    SqlSession session = MyBatisUtils.getSession();
    WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
    workerMapper.deleteWorkerById(1);
    session.commit();
    MyBatisUtils.close(session);
}

@Test
public void testGetWorkerById(){

    SqlSession session = MyBatisUtils.getSession();
    WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
    Worker worker= workerMapper.getWorkerById(2);
    System.out.println(worker);
    MyBatisUtils.close(session);
}

@Test
public void testGetWorkers(){

    SqlSession session = MyBatisUtils.getSession();
    WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
    List<Worker> workerList=workerMapper.getWorkers();
    workerList.forEach(System.out::println);
    MyBatisUtils.close(session);
}
}

(五)使用注解实现复杂关系映射开发

        1、复杂关系映射的注解介绍

注解 属性 格式
@Results 代替的是标签<resultMap>

@Results({@Result(),@Result()})

或@Results(@Result())

@Result 代替了<id>标签和<result>标签

one需要使用的@One注解(@Result(one=@one)()))

many需要使用的@Many注解(@Result(many=@many))

@One 代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象 @Result(column=" ",property="",one=@One(select=""))
@Many 代替了<Collection>标签,是多表查询的关键,在注解中用来指定子查询返回对象集合 @Result(property=" ",column=" ",many=@Many(select=""))

        2、使用注解实现一对一复杂关系映射及延迟加载

        (1)添加Person实体类及IdCard实体类

                Person实体类:

public class Person {

private int id;
private String name;
private IdCard idCard;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public IdCard getIdCard() {
    return idCard;
}

public void setIdCard(IdCard idCard) {
    this.idCard = idCard;
}
}

       IdCard实体类:

public class IdCard {

private int id;
private String cardno;
private Date useLife;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getCardno() {
    return cardno;
}

public void setCardno(String cardno) {
    this.cardno = cardno;
}

public Date getUseLife() {
    return useLife;
}

public void setUseLife(Date useLife) {
    this.useLife = useLife;
}

}

         (2)添加IdCard的持久层接口并使用注解配置

public interface IdCardMapper {
    
@Select("select * from idcard where c_id=#{id}")
@Results({
    @Result(column = "c_id",property = "id"),
    @Result(column = "c_cardno",property = "cardno"),
    @Result(column = "e_uselife",property = "useLife")
})

public IdCard getIdCardByPersonId(int id);
}

        (3)添加Person持久层接口并使用注解配置

public interface PersonMapper {

@Select(select * from person where p_id=#{id})
@Results({
    @Result(column = "p_id",property = "id"),
    @Result(column = "p_name",property = "name"),
    @Result(property = "idCard",javaType = IdCard.class,column = "p_id",one = @One(select =
"cn.offcn.dao.IdCardDao.getIdCardByPersonId",fetchType = FetchType.LAZY))
})
public Person getPersonById(int id);
}

        (4)测试一对一关联及延迟加载

@Test
public void testGetPersonById(){

    SqlSession session=MyBatisUtils.getSession();
    PersonMapper personMapper=session.getMapper(PersonMapper.class);
    Person person=personMapper.getPersonById(1);
    System.out.println(person)
    MyBatisUtils.close(session);
}

        3、使用注解实现一对多复杂关系映射

        (1)构建Department和Employee实体类

                Department实体类:

public class Department {

private int id;
private String name;
public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

                Employee实体类:

public class Employee {

private int id;
private String name;
private String gender;
private Integer age;
public Employee(){}

public Employee(int id,String name, String gender, int age) {
    this.id=id;
    this.name = name;
    this.gender = gender;
    this.age = age;
}

public Employee(String name, String gender, int age) {
    this.name = name;
    this.gender = gender;
    this.age = age;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getGender() {
    return gender;
}

public void setGender(String gender) {
    this.gender = gender;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}
}

        (2)Department实体类加入List

private List<Employee> emps;
public List<Employee> getEmps() {
    return emps;
}

public void setEmps(List<Employee> emps) {
    this.emps = emps;
}

        (3)编写EmployeeMapper持久层接口并使用注解配置

public interface EmployeeMapper{

@Select("select * from employee where e_depart_id=#{id}")
@Results({
    @Result(column = "e_id",property = "id"),
    @Result(column = "e_name",property = "name"),
    @Result(column = "e_gender",property = "gender"),
    @Result(column = "e_age",property = "age")
})
public List<Employee> getEmployeeByDepartId(int id);

}

        (4)编写DepartmentMapper持久层接口使用注解配置

public interface DepartmentDao {

@Select("select d_id id,d_name name from department where d_id=#{id}")
public Department getDepartmentById(int id);

@Select("select * from department where d_id=#{id}")
@Results({
    @Result(column = "d_id",property = "id"),
    @Result(column = "d_name",property = "name"),
    @Result(property = "emps",column = "d_id",many = @Many(select ="cn.offcn.dao.EmployeeMapper.getEmployeeByDepartId",fetchType =FetchType.LAZY))
})
public Department getDepartmentById(int id);
}

        (5)添加测试方法

public void testGetDepartmentById(){

    SqlSession session=MyBatisUtils.getSession();
    DepartmentMapper departmentMapper=session.getMapper(DepartmentMapper.class);
    Department department=departmentMapper.getDepartmentById(1);
    System.out.println(department)
    MyBatisUtils.close(session);
}

猜你喜欢

转载自blog.csdn.net/m0_67296957/article/details/127887753