Mybatis的注解开发&构建 SQL 语句
1.Mybatis的注解开发
1.1 MyBatis的常用注解
这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,我们除了可以使用映射配置文件来操作以外,还可以使用注解形式来操作,这样我们就可以减少编写Mapper。
常用注解
@Select(“查询的 SQL 语句”):执行查询操作注解
@Insert(“新增的 SQL 语句”):执行新增操作注解
@Update(“修改的 SQL 语句”):执行修改操作注解
@Delete(“删除的SQL 语句”):执行删除操作注解
1.2 MyBatis的增删改查
//StudentMapper编写
public interface StudentMapper {
//查询全部
@Select("SELECT * FROM student")
public abstract List<Student> selectAll();
//新增操作
@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
public abstract Integer insert(Student stu);
//根据id修改操作
@Update("update student set name=#{name},age=#{age} where id=#{id}")
Integer updateById(Student student);
//根据id删除操作
@Delete("delete from student where id=#{id}")
Integer deleteById(Integer id);
}
//测试类编写
package com.itheima.test;
import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test01 {
private StudentMapper mapper;
private SqlSession sqlSession;
private InputStream is;
public Test01() {
is = null;
try {
is = Resources.getResourceAsStream("MyBatisConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
mapper = sqlSession.getMapper(StudentMapper.class);
}
//查询全部
@Test
public void selectAll() throws Exception{
//5.调用实现类对象中的方法,接收结果
List<Student> list = mapper.selectAll();
//6.处理结果
for (Student student : list) {
System.out.println(student);
}
//7.释放资源
sqlSession.close();
is.close();
}
//新增操作
@Test
public void insert() throws Exception{
//5.调用实现类对象中的方法,接收结果
Student stu = new Student(4,"赵六",26);
Integer result = mapper.insert(stu);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
//修改操作
@Test
public void update() throws Exception{
//5.调用实现类对象中的方法,接收结果
Student student=new Student(3,"王虎",55);
Integer result = mapper.updateById(student);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
//删除操作
@Test
public void delete() throws Exception{
//5.调用实现类对象中的方法,接收结果
Integer result = mapper.deleteById(4);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
}
开发步骤小结:
注解实现查询操作
创建接口和查询方法
在核心配置文件中配置映射关系
编写测试类
注解实现新增操作
创建新增方法
编写测试类
注解实现修改操作
创建修改方法
编写测试类
注解实现删除操作
创建删除方法
编写测试类
修改MyBatis的核心配置文件
我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可
<mappers>
<!--扫描使用注解的类-->
<mapper class="com.itheima.mapper.StudentMapper"></mapper>
</mappers>
或者指定扫描包含映射关系的接口所在的包也可以
<mappers>
<!--扫描使用注解的类所在的包-->
<package name="com.itheima.mapper"></package>
</mappers>
1.3 MyBatis的注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
1.4 一对一查询
1.4.1 一对一查询的模型
身份证号表和人物表的关系为,一个人有一个身份证号,一个身份证号只从属于一个人
一对一查询的需求:查询每身份证号,与此同时查询出该身份证所属的人
1.4.2 一对一查询的语句
对应的sql语句:
select * from card
select * from person where id=#{id}(身份证)
1.4.3 创建Card和Person实体
public class Card {
private Integer id; //主键id
private String number; //身份证号
private Person p; //所属人的对象
}
public class Person {
private Integer id; //主键id
private String name; //人的姓名
private Integer age; //人的年龄
}
1.4.5 使用注解配置Mapper
package com.itheima.one_to_one;
import com.itheima.bean.Person;
import org.apache.ibatis.annotations.Select;
public interface PersonMapper {
//根据id查询
@Select("select * from person where id=#{id}")
public abstract Person selectById(Integer id);
}
package com.itheima.one_to_one;
import com.itheima.bean.Card;
import com.itheima.bean.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface CardMapper {
//查询全部
@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.itheima.one_to_one.PersonMapper.selectById")
)
})
public abstract List<Card> selectAll();
}
1.4.6 测试类
package com.itheima.one_to_one;
import com.itheima.bean.Card;
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.Test;
import java.io.InputStream;
import java.util.List;
public class Test01 {
@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 = sqlSessionFactory.openSession(true);
//4.获取CardMapper接口的实现类对象
CardMapper mapper = sqlSession.getMapper(CardMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Card> list = mapper.selectAll();
//6.处理结果
for (Card card : list) {
System.out.println(card);
}
//7.释放资源
sqlSession.close();
is.close();
}
}
1.5 一对多查询
1.5.1 一对多查询的模型
学生表和班级表的关系为,一个班级有多个学生,一个学生只从属于一个班级
一对多查询的需求:查询一个班级,与此同时查询出该班级所有的学生
1.5.2 一对多查询的语句
对应的sql语句:
select * from classes
select * from student where id=#{id}(班级)
1.5.3 创建Classes和Student实体
public class Classes {
private Integer id; //主键id
private String name; //班级名称
private List<Student> students; //班级中所有学生对象
}
public class Student {
private Integer id; //主键id
private String name; //学生姓名
private Integer age; //学生年龄
}
1.5.5 使用注解配置Mapper
package com.itheima.one_to_many;
import com.itheima.bean.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
//根据cid查询student表
@Select("select * from student where cid=#{cid}")
public abstract List<Student> selectByCid(Integer cid);
}
package com.itheima.one_to_many;
import com.itheima.bean.Classes;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface ClassesMapper {
//查询全部
@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.itheima.one_to_many.StudentMapper.selectByCid")
)
})
public abstract List<Classes> selectAll();
}
1.5.6 测试类
package com.itheima.one_to_many;
import com.itheima.bean.Classes;
import com.itheima.bean.Student;
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.Test;
import java.io.InputStream;
import java.util.List;
public class Test01 {
@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 = sqlSessionFactory.openSession(true);
//4.获取ClassesMapper接口的实现类对象
ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Classes> list = mapper.selectAll();
//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();
}
}
1.6 多对多查询
1.6.1 多对多查询的模型
学生表和课程表的关系为,一个用户有多门课程,一门课程被多个学生选择
多对多查询的需求:查询学生同时查询出该学生的所有选择的课程
1.6.2 多对多查询的语句
对应的sql语句:
select distinct s.id,s.name,s.age from student s,stu_cr sc where sc.sid=s.id
select c.id,c.name from stu_cr sc,course c where sc.cid=c.id and sc.sid=#{id}(sc.cid)
1.6.3 创建Course实体,修改Student实体
public class Course {
private Integer id; //主键id
private String name; //课程名称
}
public class Student {
private Integer id; //主键id
private String name; //学生姓名
private Integer age; //学生年龄
private List<Course> courses; //学生所选择的课程对象
}
1.6.5 使用注解配置Mapper
package com.itheima.many_to_many;
import com.itheima.bean.Course;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface CourseMapper {
//根据学生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);
}
package com.itheima.many_to_many;
import com.itheima.bean.Student;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
//查询全部
@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.itheima.many_to_many.CourseMapper.selectBySid")
)
})
public abstract List<Student> selectAll();
}
1.6.6 测试类
package com.itheima.many_to_many;
import com.itheima.bean.Course;
import com.itheima.bean.Student;
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.Test;
import java.io.InputStream;
import java.util.List;
public class Test01 {
@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 = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Student> list = mapper.selectAll();
//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();
}
}
核心配置文件中添加包扫描
<!--配置映射关系-->
<mappers>
<package name="com.itheima"/>
</mappers>
注解多表操作小结:
@Results:封装映射关系的父注解。
Result[] value():定义了Result 数组
@Result:封装映射关系的子注解。
column 属性:查询出的表中字段名称
property 属性:实体对象中的属性名称
javaType 属性:被包含对象的数据类型
one 属性:一对一查询固定属性
many 属性:一对多查询固定属性
@One:一对一查询的注解。
select 属性:指定调用某个接口中的方法
@Many:一对多查询的注解。
select 属性:指定调用某个接口中的方法