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注解组合完成复杂关系的配置

Mybatis的注解开发&构建 SQL 语句

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 属性:指定调用某个接口中的方法

 
2.MyBatis构建 SQL 语句
 
2.1 SQL 构建对象介绍
我们之前通过注解开发时,相关 SQL 语句都是自己直接拼写的。一些关键字写起来比较麻烦、而且容易出错。
MyBatis 给我们提供了 org.apache.ibatis.jdbc.SQL功能类,专门用于构建SQL 语句。
Mybatis的注解开发&构建 SQL 语句
 
2.2 增删改查操作
 
2.2.1 构建sql语句
package com.itheima.sql;
 
import com.itheima.bean.Student;
import org.apache.ibatis.jdbc.SQL;
 
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.2.2 编写StudentMapper添加sql语句注释
package com.itheima.mapper;
 
import com.itheima.bean.Student;
import com.itheima.sql.ReturnSql;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
 
import java.util.List;
 
public interface StudentMapper {
//查询全部0
//@Select("SELECT * FROM student")
@SelectProvider(type = ReturnSql.class , method = "getSelectAll")
public abstract List<Student> selectAll();
 
//新增功能
//@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
@InsertProvider(type = ReturnSql.class , method = "getInsert")
public abstract Integer insert(Student stu);
 
//修改功能
//@Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
@UpdateProvider(type = ReturnSql.class , method = "getUpdate")
public abstract Integer update(Student stu);
 
//删除功能
//@Delete("DELETE FROM student WHERE id=#{id}")
@DeleteProvider(type = ReturnSql.class , method = "getDelete")
public abstract Integer delete(Integer id);
}
 
2.2.3 编写测试类
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 {
 
StudentMapper mapper;
SqlSession sqlSession;
InputStream is;
 
public Test01() {
is = null;
try {
//1.加载核心配置文件
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 stu = new Student(4,"赵六",36);
Integer result = mapper.update(stu);
 
//6.处理结果
System.out.println(result);
 
//7.释放资源
sqlSession.close();
is.close();
}
 
@Test
public void delete() throws Exception{
 
//5.调用实现类对象中的方法,接收结果
Integer result = mapper.delete(4);
 
//6.处理结果
System.out.println(result);
 
//7.释放资源
sqlSession.close();
is.close();
}
}
2.2.4 核心配置文件中添加包扫描
<!--配置映射关系-->
<mappers>
<package name="com.itheima"/>
</mappers>