第十节:MyBatis之常用注解、注解的多表操作、构建SQL
一. 常用注解
1. 简介
Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。常用注解如下:
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
2. 实战
(1). 核心配置文件(已经没有映射配置文件了)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8" ?> <!--MyBatis的DTD约束--> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration 核心根标签--> <configuration> <!--引入数据库连接的配置文件--> <properties resource="jdbc.properties"/> <!--配置LOG4J--> <settings> <setting name="logImpl" value="log4j"/> </settings> <!--起别名--> <typeAliases> <!--<typeAlias type="com.ypf.bean.Student" alias="student"/>--> <!-- 全局别名通用配置 --> <package name="com.ypf.bean"/> </typeAliases> <!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个--> <environments default="mysql"> <!--environment配置数据库环境 id属性唯一标识--> <environment id="mysql"> <!-- transactionManager事务管理。 type属性,采用JDBC默认的事务--> <transactionManager type="JDBC"></transactionManager> <!-- dataSource数据源信息 type属性 连接池--> <dataSource type="POOLED"> <!-- property获取数据库连接的配置信息 --> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!-- mappers引入映射配置文件 --> <mappers> <!--扫描使用注解的类--> <!-- <mapper class="com.ypf.dao.StudentDao"></mapper>--> <!-- 或 扫描使用注解的类所在的包--> <package name="com.ypf.dao"></package> </mappers> </configuration>
(2). 代理接口
public interface StudentDao { //查询全部 @Select("SELECT * FROM student") public abstract List<Student> selectAll(); //新增操作 @Insert("INSERT INTO student VALUES (#{id},#{name},#{age})") public abstract Integer insert(Student stu); //修改操作 @Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}") public abstract Integer update(Student stu); //删除操作 @Delete("DELETE FROM student WHERE id=#{id}") public abstract Integer delete(Integer id); }
(3). 测试代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 查询全部 */ @Test public void selectAll() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过SqlSession工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.获取StudentDao实现类对象,并调用相关方法 StudentDao sDao=sqlSession.getMapper(StudentDao.class); List<Student> list=sDao.selectAll(); //5.处理结果 for (Student stu : list) { System.out.println(stu); } //7.释放资源 sqlSession.close(); is.close(); } /* 删除功能 */ @Test public void delete() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取StudentDao实现类对象,并调用相关方法 StudentDao sDao=sqlSession.getMapper(StudentDao.class); int result=sDao.delete(5); //5.提交事务 sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); } /* 修改功能 */ @Test public void update() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取StudentDao实现类对象,并调用相关方法 Student stu = new Student(5,"周七",37); StudentDao sDao=sqlSession.getMapper(StudentDao.class); int result=sDao.update(stu); //5.提交事务 sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); } /* 新增功能 */ @Test public void insert() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 //SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(true); //设为true,表示自动提交事务,后面则不需要sqlSession.commit了 //4.获取StudentDao实现类对象,并调用相关方法 Student stu = new Student(5,"周七",27); StudentDao sDao=sqlSession.getMapper(StudentDao.class); int result = sDao.insert( stu); //5.提交事务 //sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); }
二. 注解的多表操作
1. 整体说明
实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置。
2. 实战
(1). 代理接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public interface DynamicMapper { //查询全部(1对1 ) @Select("SELECT * FROM card") @Results({ @Result(column = "id",property = "id"), @Result(column = "number",property = "number"), @Result( property = "p", // 被包含对象的变量名 javaType = Person.class, // 被包含对象的实际数据类型(关联类) column = "pid", // 根据查询出的card表中的pid字段来查询person表 /* one、@One 一对一固定写法 select属性:指定调用哪个接口中的哪个方法 */ one = @One(select = "com.ypf.dao.DynamicMapper.selectById") ) }) public abstract List<Card> selectAll(); //根据id查询(1对1) @Select("SELECT * FROM person WHERE id=#{id}") public abstract Person selectById(Integer id); //1个班级对应多个学生(1对多) @Select("SELECT * FROM classes") @Results({ @Result(column = "id",property = "id"), @Result(column = "name",property = "name"), @Result( property = "students", // 被包含对象的变量名 javaType = List.class, // 被包含对象的实际数据类型 column = "id", // 根据查询出的classes表的id字段来查询student表 /* many、@Many 一对多查询的固定写法 select属性:指定调用哪个接口中的哪个查询方法 */ many = @Many(select = "com.ypf.dao.DynamicMapper.selectByCid") ) }) public abstract List<Classes> selectAll2(); //根据cid查询student表 @Select("SELECT * FROM student WHERE cid=#{cid}") public abstract List<Student> selectByCid(Integer cid); //查询全部(多对多 课程和学生是多对多的关系) @Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id") @Results({ @Result(column = "id",property = "id"), @Result(column = "name",property = "name"), @Result(column = "age",property = "age"), @Result( property = "courses", // 被包含对象的变量名 javaType = List.class, // 被包含对象的实际数据类型 column = "id", // 根据查询出student表的id来作为关联条件,去查询中间表和课程表 /* many、@Many 一对多查询的固定写法 select属性:指定调用哪个接口中的哪个查询方法 */ many = @Many(select = "com.ypf.dao.DynamicMapper.selectBySid") ) }) public abstract List<Student> selectAll3(); //根据学生id查询所选课程 @Select("SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#{id}") public abstract List<Course> selectBySid(Integer id); }
(2). 测试类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class AnnotationRelationTest { @Test public void selectOneToOne() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取DynamicMapper接口的实现类对象 DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class); //5.调用实现类对象中的方法,接收结果 List<Card> list = mapper.selectAll(); //6.处理结果 for (Card card : list) { System.out.println(card); } //7.释放资源 sqlSession.close(); is.close(); } @Test public void selectOneToMany() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取DynamicMapper接口的实现类对象 DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class); //5.调用实现类对象中的方法,接收结果 List<Classes> list = mapper.selectAll2(); //6.处理结果 for (Classes cls : list) { System.out.println(cls.getId() + "," + cls.getName()); List<Student> students = cls.getStudents(); for (Student student : students) { System.out.println("\t" + student); } } //7.释放资源 sqlSession.close(); is.close(); } @Test public void selectManyToMany() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取DynamicMapper接口的实现类对象 DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class); //5.调用实现类对象中的方法,接收结果 List<Student> list = mapper.selectAll3(); //6.处理结果 for (Student student : list) { System.out.println(student.getId() + "," + student.getName() + "," + student.getAge()); List<Course> courses = student.getCourses(); for (Course cours : courses) { System.out.println("\t" + cours); } } //7.释放资源 sqlSession.close(); is.close(); } }
三. 构建SQL
1. 说明
上述通过注解开发时,相关 SQL 语句都是自己直接拼写的。一些关键字写起来比较麻烦、而且容易出错。 MyBatis 给我们提供了 org.apache.ibatis.jdbc.SQL 功能类,专门用于构建 SQL 语句。
2. 实战测试
(1). SQL构建类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class ReturnSql { //定义方法,返回查询的sql语句 public String getSelectAll() { return new SQL() { { SELECT("*"); FROM("student"); } }.toString(); } //定义方法,返回新增的sql语句 public String getInsert(Student stu) { return new SQL() { { INSERT_INTO("student"); INTO_VALUES("#{id},#{name},#{age}"); } }.toString(); } //定义方法,返回修改的sql语句 public String getUpdate(Student stu) { return new SQL() { { UPDATE("student"); SET("name=#{name}","age=#{age}"); WHERE("id=#{id}"); } }.toString(); } //定义方法,返回删除的sql语句 public String getDelete(Integer id) { return new SQL() { { DELETE_FROM("student"); WHERE("id=#{id}"); } }.toString(); } }
(2). 代理接口
public interface DynamicMapper { //查询全部 @SelectProvider(type = ReturnSql.class , method = "getSelectAll") public abstract List<Student> selectAll(); //新增功能 @InsertProvider(type = ReturnSql.class , method = "getInsert") public abstract Integer insert(Student stu); //修改功能 @UpdateProvider(type = ReturnSql.class , method = "getUpdate") public abstract Integer update(Student stu); //删除功能 @DeleteProvider(type = ReturnSql.class , method = "getDelete") public abstract Integer delete(Integer id); }
(3). 测试类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class DynamicSQLTest { /* 查询全部 */ @Test public void selectAll() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过SqlSession工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.获取DynamicMapper实现类对象,并调用相关方法 DynamicMapper sDao=sqlSession.getMapper(DynamicMapper.class); List<Student> list=sDao.selectAll(); //5.处理结果 for (Student stu : list) { System.out.println(stu); } //7.释放资源 sqlSession.close(); is.close(); } /* 删除功能 */ @Test public void delete() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取DynamicMapper实现类对象,并调用相关方法 DynamicMapper sDao=sqlSession.getMapper(DynamicMapper.class); int result=sDao.delete(5); //5.提交事务 sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); } /* 修改功能 */ @Test public void update() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取DynamicMapper实现类对象,并调用相关方法 Student stu = new Student(5,"周七",37); DynamicMapper sDao=sqlSession.getMapper(DynamicMapper.class); int result=sDao.update(stu); //5.提交事务 sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); } /* 新增功能 */ @Test public void insert() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 //SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(true); //设为true,表示自动提交事务,后面则不需要sqlSession.commit了 //4.获取DynamicMapper实现类对象,并调用相关方法 Student stu = new Student(5,"周七",27); DynamicMapper sDao=sqlSession.getMapper(DynamicMapper.class); int result = sDao.insert( stu); //5.提交事务 //sqlSession.commit(); //6.处理结果 System.out.println(result); //7.释放资源 sqlSession.close(); is.close(); } }
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。