MyBatis学习总结(十一):MyBatis的纯注解开发

MyBatis的纯注解方式去掉了原来的mapper文件,不用写实体类的配置文件,直接在接口里面写查询语句,在SqlMapperConfig.xml只需要指定接口所在的包即可。接下来就用一个案例部门和员工来实现纯注解开发。

(1)创建maven工程,导入jar包。

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.25</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

  </dependencies>

(2)数据库文件的准备。

t_dept文件:

CREATE TABLE `t_dept` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dept_name` varchar(20) DEFAULT NULL,
  `dept_desc` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
insert into t_dept(dept_name, dept_age) values("开发部","软件开发");
insert into t_dept(dept_name, dept_age) values("测试部","软件测试");
insert into t_dept(dept_name, dept_age) values("财务部","发放钱财");
insert into t_dept(dept_name, dept_age) values("人事部","招聘员工");
 

 t_emp文件:

CREATE TABLE `t_emp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `emp_name` varchar(20) DEFAULT NULL,
  `emp_age` int(11) DEFAULT NULL,
  `dept_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `dept_id` (`dept_id`),
  CONSTRAINT `t_emp_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`id`)
);
INSERT INTO `t_emp` VALUES (1,'张倩',22,2),(2,'杨帆',24,1),(3,'章飞',21,3),(4,'李冰',51,4),(5,'王猛',36,3),(6,'康生',26,1),(7,'刘婷',20,3),(8,'刘羽',22,2);

(3)在dao包下创建实体类员工类和部门类。

部门类:

public class Department {
    private Integer id;
    private String deptName;
    private String deptDesc;

    private List<Emp> empList;

    public Integer getId() {
        return id;
    }

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

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getDeptDesc() {
        return deptDesc;
    }

    public void setDeptDesc(String deptDesc) {
        this.deptDesc = deptDesc;
    }

    public List<Emp> getEmpList() {
        return empList;
    }

    public void setEmpList(List<Emp> empList) {
        this.empList = empList;
    }

    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", deptName='" + deptName + '\'' +
                ", deptDesc='" + deptDesc + '\'' +
                ", empList=" + empList +
                '}';
    }
}

员工类:

public class Emp {
    private Integer id;
    private String empName;
    private Integer empAge;
    private Integer deptId;


    public Emp() {
    }

    public Integer getId() {
        return id;
    }

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

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getEmpAge() {
        return empAge;
    }

    public void setEmpAge(Integer empAge) {
        this.empAge = empAge;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }


    @Override
    public String toString() {
        return "Staff{" +
                "id=" + id +
                ", empName='" + empName + '\'' +
                ", empAge=" + empAge +
                ", deptId=" + deptId +
                '}';
    }
}

(4)在dao包下创建IDepartmentDao和IEmpDao。

IDepartmentDao:


public interface IDepartmentDao {
    @Select(value = "select * from t_dept")
    @Results(value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "dept_name", property = "deptName"),
            @Result(column = "dept_desc", property = "deptDesc"),
            @Result(column = "id", property = "empList", javaType = List.class,many = @Many(select = "com.dao.IEmpDao.findByDeptId"))
    })
    List<Department> findAll();
    @Select(value = "select * from t_dept where id = #{id}")
    @Results(value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "dept_name", property = "deptName"),
            @Result(column = "dept_desc", property = "deptDesc")
    })
    List<Department> findById(int id);


}

IEmpDao:

public interface IEmpDao {
    @Select("select * from t_emp")
    @Results(id = "empMap",value={
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "emp_name", property = "empName"),
            @Result(column = "emp_age", property = "empAge"),
            @Result(property = "department", column = "dept_id", one = @One(select = "com.dao.IDepartmentDao.findById", fetchType = FetchType.EAGER))
    })
    List<Emp> findDepartment();

    @Select("select * from t_emp where id = #{id}")
    @Results(value={
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "emp_name", property = "empName"),
            @Result(column = "emp_age", property = "empAge"),
    })
    List<Emp> findByDeptId(int id);

}

(5)在resources目录下引入log4j.properties和SqlMapperConfig.xml。

log4j.properties:

### 设置###
log4j.rootLogger = debug,stdout

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
pender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

SqlMapperConfig.xml:

<?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>
    <!--  配置环境  -->
    <environments default="mysql">
        <!--     配置MySQL的环境   -->
        <environment id="mysql">
            <!--     配置事务的类型       -->
            <transactionManager type="JDBC"></transactionManager>
            <!--     配置数据源(连接池)       -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///universaldb"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--接口的注册-->
    <!--之前是配置实体类的映射文件,现在没有了,直接配置接口-->
    <mappers>
       <package name="com.dao"/>
    </mappers>

</configuration>

(6)创建测试类

package com;

import com.dao.IDepartmentDao;
import com.dao.IEmpDao;
import com.entity.Department;
import com.entity.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * 功能描述:
 *
 * @Author: aaa
 * @Date: 2021/2/18 11:33
 */
public class TestAnno {
    InputStream in = null;
    SqlSessionFactoryBuilder builder = null;
    SqlSessionFactory factory = null;
    SqlSession sqlSession = null;

    @Before
    public void init() throws IOException {
        //1、读取配置文件
        in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        sqlSession = factory.openSession();
    }
    @After
    public void destory() throws IOException {
        sqlSession.commit();
        sqlSession.close();
        in.close();
    }

    @Test
    public void testDeptAll(){
        IDepartmentDao departmentDao = sqlSession.getMapper(IDepartmentDao.class);
        List<Department> departmentList = departmentDao.findAll();
        System.out.println(departmentList);
    }

    @Test
    public void testeMPAll(){
        IEmpDao staffAnnoDao = sqlSession.getMapper(IEmpDao.class);
        List<Emp> empList = staffAnnoDao.findDepartment();
        System.out.println(empList);
    }

}

MyBatis多参数查询的注解开发方式如下:

    @Select("select * from t_people where name=#{name} and address=#{address}")
    List<People> findByMorePara(@Param("name") String name, @Param("address") String address);

以上就是MyBatis注解开发的案例。

总结:

1、@Results各个属性的含义

(1)id为当前结果集声明唯一标识。

(2)value值为结果集映射关系。

(3)@Result代表一个字段的映射关系。

  • column指定数据库字段的名称。
  • property指定实体类属性的名称。
  • dbcType数据库字段类型,@Result里的id值为true表明主键,默认false;

(4)使用@ResultMap来引用映射结果集,其中value可省略。当这段@Results代码需要在多个方法用到时,为了提高代码复用性,可以为这个@Results注解设置id,然后使用@ResultMap注解来复用这段代码。

(5)案例:

@Select(value = "select * from t_dept")
@Results(value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "dept_name", property = "deptName"),
            @Result(column = "dept_desc", property = "deptDesc")
    })
List<Department> findAll();

2、one和Many的用法

(1)One的用法

当我们需要通过查询到的一个字段值作为参数,去执行另外一个方法来查询关联的内容,而且两者是一对一关系时,可以使用@One注解来便捷的实现。比如当我们需要查询学生信息以及其所属班级信息时,需要以查询到的class_id为参数,来执行ClassesMapper中的selectById方法,从而获得学生所属的班级信息.

案例:

@Select("select * from t_emp")
    @Results(id = "empMap",value={
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "emp_name", property = "empName"),
            @Result(column = "emp_age", property = "empAge"),
            @Result(property = "department", column = "dept_id", one = @One(select = "com.dao.IDepartmentDao.findById", fetchType = FetchType.EAGER))
    })
 List<Emp> findDepartment();

(2)Many的用法

与@One类似,只不过如果使用@One查询到的结果是多行,会抛出TooManyResultException异常,这种时候应该使用的是@Many注解,实现一对多的查询。比如在需要查询学生信息和每次考试的成绩信息时.

案例:

@Select(value = "select * from t_dept")
    @Results(value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "dept_name", property = "deptName"),
            @Result(column = "dept_desc", property = "deptDesc"),
            @Result(column = "id", property = "empList", javaType = List.class,many = @Many(select = "com.dao.IEmpDao.findByDeptId"))
    })
    List<Department> findAll();

错误总结:

问题一:Result Maps collection already contains value for com.dao.IEmpDao.empMap。

原因:在IEmpDao中存在id为"empMap"的resultMap值

问题二:MyBatis一对多只显示一个结果的问题。

原因:在一对多操作中的两张表,它们的主键名称相同引发的问题,只要设置为不同的主键名称就可以了。即:实体类的属性名可以相同,数据库的列名要不同。例如:员工表的主键为id,部门表的主键也为id,就会引发上面的问题。如果员工表的主键改为emp_id,部门表的主键改为dept_id,则不会触发此问题。

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/113843770