当前位置:   article > 正文

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

mybatis纯注解

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

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

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
  9. <dependency>
  10. <groupId>org.mybatis</groupId>
  11. <artifactId>mybatis</artifactId>
  12. <version>3.5.0</version>
  13. </dependency>
  14. <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  15. <dependency>
  16. <groupId>mysql</groupId>
  17. <artifactId>mysql-connector-java</artifactId>
  18. <version>5.1.25</version>
  19. </dependency>
  20. <!-- https://mvnrepository.com/artifact/log4j/log4j -->
  21. <dependency>
  22. <groupId>log4j</groupId>
  23. <artifactId>log4j</artifactId>
  24. <version>1.2.17</version>
  25. </dependency>
  26. </dependencies>

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

t_dept文件:

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

 t_emp文件:

  1. CREATE TABLE `t_emp` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `emp_name` varchar(20) DEFAULT NULL,
  4. `emp_age` int(11) DEFAULT NULL,
  5. `dept_id` int(11) NOT NULL,
  6. PRIMARY KEY (`id`),
  7. KEY `dept_id` (`dept_id`),
  8. CONSTRAINT `t_emp_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`id`)
  9. );
  10. 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包下创建实体类员工类和部门类。

部门类:

  1. public class Department {
  2. private Integer id;
  3. private String deptName;
  4. private String deptDesc;
  5. private List<Emp> empList;
  6. public Integer getId() {
  7. return id;
  8. }
  9. public void setId(Integer id) {
  10. this.id = id;
  11. }
  12. public String getDeptName() {
  13. return deptName;
  14. }
  15. public void setDeptName(String deptName) {
  16. this.deptName = deptName;
  17. }
  18. public String getDeptDesc() {
  19. return deptDesc;
  20. }
  21. public void setDeptDesc(String deptDesc) {
  22. this.deptDesc = deptDesc;
  23. }
  24. public List<Emp> getEmpList() {
  25. return empList;
  26. }
  27. public void setEmpList(List<Emp> empList) {
  28. this.empList = empList;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Department{" +
  33. "id=" + id +
  34. ", deptName='" + deptName + '\'' +
  35. ", deptDesc='" + deptDesc + '\'' +
  36. ", empList=" + empList +
  37. '}';
  38. }
  39. }

员工类:

  1. public class Emp {
  2. private Integer id;
  3. private String empName;
  4. private Integer empAge;
  5. private Integer deptId;
  6. public Emp() {
  7. }
  8. public Integer getId() {
  9. return id;
  10. }
  11. public void setId(Integer id) {
  12. this.id = id;
  13. }
  14. public String getEmpName() {
  15. return empName;
  16. }
  17. public void setEmpName(String empName) {
  18. this.empName = empName;
  19. }
  20. public Integer getEmpAge() {
  21. return empAge;
  22. }
  23. public void setEmpAge(Integer empAge) {
  24. this.empAge = empAge;
  25. }
  26. public Integer getDeptId() {
  27. return deptId;
  28. }
  29. public void setDeptId(Integer deptId) {
  30. this.deptId = deptId;
  31. }
  32. @Override
  33. public String toString() {
  34. return "Staff{" +
  35. "id=" + id +
  36. ", empName='" + empName + '\'' +
  37. ", empAge=" + empAge +
  38. ", deptId=" + deptId +
  39. '}';
  40. }
  41. }

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

IDepartmentDao:

  1. public interface IDepartmentDao {
  2. @Select(value = "select * from t_dept")
  3. @Results(value = {
  4. @Result(id=true, column = "id", property = "id"),
  5. @Result(column = "dept_name", property = "deptName"),
  6. @Result(column = "dept_desc", property = "deptDesc"),
  7. @Result(column = "id", property = "empList", javaType = List.class,many = @Many(select = "com.dao.IEmpDao.findByDeptId"))
  8. })
  9. List<Department> findAll();
  10. @Select(value = "select * from t_dept where id = #{id}")
  11. @Results(value = {
  12. @Result(id=true, column = "id", property = "id"),
  13. @Result(column = "dept_name", property = "deptName"),
  14. @Result(column = "dept_desc", property = "deptDesc")
  15. })
  16. List<Department> findById(int id);
  17. }

IEmpDao:

  1. public interface IEmpDao {
  2. @Select("select * from t_emp")
  3. @Results(id = "empMap",value={
  4. @Result(id=true, column = "id", property = "id"),
  5. @Result(column = "emp_name", property = "empName"),
  6. @Result(column = "emp_age", property = "empAge"),
  7. @Result(property = "department", column = "dept_id", one = @One(select = "com.dao.IDepartmentDao.findById", fetchType = FetchType.EAGER))
  8. })
  9. List<Emp> findDepartment();
  10. @Select("select * from t_emp where id = #{id}")
  11. @Results(value={
  12. @Result(id=true, column = "id", property = "id"),
  13. @Result(column = "emp_name", property = "empName"),
  14. @Result(column = "emp_age", property = "empAge"),
  15. })
  16. List<Emp> findByDeptId(int id);
  17. }

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

log4j.properties:

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

SqlMapperConfig.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!-- 配置环境 -->
  7. <environments default="mysql">
  8. <!-- 配置MySQL的环境 -->
  9. <environment id="mysql">
  10. <!-- 配置事务的类型 -->
  11. <transactionManager type="JDBC"></transactionManager>
  12. <!-- 配置数据源(连接池) -->
  13. <dataSource type="POOLED">
  14. <property name="driver" value="com.mysql.jdbc.Driver"/>
  15. <property name="url" value="jdbc:mysql:///universaldb"/>
  16. <property name="username" value="root"/>
  17. <property name="password" value="root"/>
  18. </dataSource>
  19. </environment>
  20. </environments>
  21. <!--接口的注册-->
  22. <!--之前是配置实体类的映射文件,现在没有了,直接配置接口-->
  23. <mappers>
  24. <package name="com.dao"/>
  25. </mappers>
  26. </configuration>

(6)创建测试类

  1. package com;
  2. import com.dao.IDepartmentDao;
  3. import com.dao.IEmpDao;
  4. import com.entity.Department;
  5. import com.entity.Emp;
  6. import org.apache.ibatis.io.Resources;
  7. import org.apache.ibatis.session.SqlSession;
  8. import org.apache.ibatis.session.SqlSessionFactory;
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  10. import org.junit.After;
  11. import org.junit.Before;
  12. import org.junit.Test;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.util.List;
  16. /**
  17. * 功能描述:
  18. *
  19. * @Author: aaa
  20. * @Date: 2021/2/18 11:33
  21. */
  22. public class TestAnno {
  23. InputStream in = null;
  24. SqlSessionFactoryBuilder builder = null;
  25. SqlSessionFactory factory = null;
  26. SqlSession sqlSession = null;
  27. @Before
  28. public void init() throws IOException {
  29. //1、读取配置文件
  30. in = Resources.getResourceAsStream("SqlMapperConfig.xml");
  31. //2、创建SqlSessionFactory工厂
  32. builder = new SqlSessionFactoryBuilder();
  33. factory = builder.build(in);
  34. //3、使用工厂生产SqlSession对象
  35. sqlSession = factory.openSession();
  36. }
  37. @After
  38. public void destory() throws IOException {
  39. sqlSession.commit();
  40. sqlSession.close();
  41. in.close();
  42. }
  43. @Test
  44. public void testDeptAll(){
  45. IDepartmentDao departmentDao = sqlSession.getMapper(IDepartmentDao.class);
  46. List<Department> departmentList = departmentDao.findAll();
  47. System.out.println(departmentList);
  48. }
  49. @Test
  50. public void testeMPAll(){
  51. IEmpDao staffAnnoDao = sqlSession.getMapper(IEmpDao.class);
  52. List<Emp> empList = staffAnnoDao.findDepartment();
  53. System.out.println(empList);
  54. }
  55. }

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

  1. @Select("select * from t_people where name=#{name} and address=#{address}")
  2. 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)案例:

  1. @Select(value = "select * from t_dept")
  2. @Results(value = {
  3. @Result(id=true, column = "id", property = "id"),
  4. @Result(column = "dept_name", property = "deptName"),
  5. @Result(column = "dept_desc", property = "deptDesc")
  6. })
  7. List<Department> findAll();

2、one和Many的用法

(1)One的用法

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

案例:

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

(2)Many的用法

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

案例:

  1. @Select(value = "select * from t_dept")
  2. @Results(value = {
  3. @Result(id=true, column = "id", property = "id"),
  4. @Result(column = "dept_name", property = "deptName"),
  5. @Result(column = "dept_desc", property = "deptDesc"),
  6. @Result(column = "id", property = "empList", javaType = List.class,many = @Many(select = "com.dao.IEmpDao.findByDeptId"))
  7. })
  8. 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,则不会触发此问题。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号