MyBatis--注解式开发
MyBatis的注解,主要是用于替换映射文件。而映射文件中无非存放着增删改查的sql映射标签。所以,MyBatis注解,就是替换映射文件中的sql标签。
常用注解说明:
注解 | 说明 |
---|---|
@Insert | 实现新增 |
@Update | 实现更新 |
@Delete | 实现删除 |
@Select | 实现查询 |
@Result | 实现结果集封装 |
@Results | 可以与@Result 一起使用,封装多个结果集 |
@ResultMap | 实现引用@Results 定义的封装 |
@One | 实现一对一结果集封装 |
@Many | 实现一对多结果集封装 |
@SelectProvider | 实现动态 SQL 映射 |
@CacheNamespace | 实现注解二级缓存的使用 |
一、基本的CRUD
1.@Insert
其value属性用于指定要执行的insert语句。
2.@SelectKey
用于替换xml中的<selectKey/>
标签,用于返回新插入数据的id值。
@SelectKey(statement="select @@identity",resultType=int.class,keyProperty="id",before=false
复制代码
- statement:获取新插入记录主键值得sql语句
- keyProperty:获取的该主键值返回后初始化对象的那个属性
- resultType:返回值类型
- before:指定主键的生成相对于insert语句的执行先后顺序,该属性不能省略
3.@Delete
其value属性用于指定要执行的delete语句。
4.@Update
其value属性用于指定要执行的update语句。
5.@Select
其value属性用于指定要执行的select语句。
程序举例:
SqlMapConfig.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>
<!-- 引入外部配置文件-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置别名-->
<typeAliases>
<package name="com.hcx.domain"></package>
</typeAliases>
<!-- 配置环境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 指定带有注解的dao接口所在位置 -->
<mappers>
<mapper class="com.hcx.dao.StudentDao"></mapper>
</mappers>
</configuration>
复制代码
1.修改dao接口:
public interface IStudentDao {
@Insert(value={"insert into student(name,age,score) values(#{name},#{age},#{score})"})
void insertStudent(Student student);
@Insert("insert into student(name,age,score) values(#{name},#{age},#{score})")
@SelectKey(statement="select @@identity",resultType=int.class,keyProperty="id",before=false)
void insertStudentCacheId(Student student);
@Delete(value="delete from student where id=#{id}")
void deleteStudentById(int id);
@Update("update student set name=#{name},age=#{age},score=#{score} where id=#{id}")
void updateStudent(Student student);
@Select("select * from student")
List<Student> selectAllStudents();
@Select("select * from student where id=#{id}")
Student selectStudentById(int id);
@Select("select * from student where name like '%' #{name} '%'")
List<Student> selectStudentsByName(String name);
}
复制代码
2.删除映射文件
3.修改主配置文件
由于没有了映射文件,所以主配置文件中不能使用<mapper/>
注册mapper的位置了。需要使用<package/>
标签
<!-- 注册映射文件 -->
<mappers>
<package name="com.hcx.dao"/>
</mappers>
复制代码
注意:使用了注解之后,不管主配置文件(SqlMapConfig.xml)有没有引用映射文件,都不能存在映射文件。可以删除或者放在其他目录下。
二、实现复杂关系映射
1.@Result 当实体属性和数据库字段名称不一致时,使用@Result
注解声明映射关系
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),
@Result(column = "name",property = "studentName"),
@Result(column = "age",property = "studentAge"),
@Result(column = "score",property = "studentScore"),
})
复制代码
id
:唯一标识这段映射,之后可以直接引用,无需重复编写 id=true
:标识为主键字段 column
:数据库字段名 property
:实体属性名
2.@ResultMap 引用定义好的ResultMap
Student:
@Data
@ToString
public class Student implements Serializable{
private Integer studentId;
private String studentName;
private int studentAge;
private double studentScore;
}
复制代码
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),
@Result(column = "name",property = "studentName"),
@Result(column = "age",property = "studentAge"),
@Result(column = "score",property = "studentScore"),
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
复制代码
AnnotationCrudTest:
public class AnnotationCrudTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private StudentDao studentDao;
@Before
public void init()throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
studentDao = session.getMapper(StudentDao.class);
}
@After
public void destroy()throws Exception{
session.commit();
session.close();
in.close();
}
@Test
public void testFindAll(){
List<Student> students = studentDao.findAll();
for(Student student : students){
System.out.println(student);
}
}
@Test
public void testFindById(){
Student student = studentDao.findById(1);
System.out.println(student);
}
@Test
public void testFindByName(){
List<Student> students = studentDao.findStudentByName("%小红%");
for(Student student : students){
System.out.println(student);
}
}
}
复制代码
三、实现多表复杂查询
1.一对一
Account:
@Data
@ToString
public class Account {
private Integer id;
private Integer studentId;
private Double money;
//多对一:一个账户只能属于一个学生
private Student student;
}
复制代码
AccountDao:
public interface AccountDao {
/**
* 查询所有账户并获取每个账户所属用户信息
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "studentId",property = "studentId"),
@Result(column = "money",property = "money"),
@Result(property = "student",column = "studentId",one = @One(select = "com.hcx.dao.StudentDao.findById",
fetchType = FetchType.EAGER))
})
List<Account> findAll();
}
复制代码
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),
@Result(column = "name",property = "studentName"),
@Result(column = "age",property = "studentAge"),
@Result(column = "score",property = "studentScore"),
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
复制代码
AccountTest:
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for(Account account : accounts){
System.out.println(account);
// System.out.println(account.getStudent());
}
}
复制代码
注意:通常对一选择立即加载,对多选择延迟加载
2.一对多
Student:
@Data
@ToString
public class Student implements Serializable{
private Integer studentId;
private String studentName;
private int studentAge;
private double studentScore;
//一对多,一个用户对应多个账户
private List<Account> accounts;
}
复制代码
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),
@Result(column = "name",property = "studentName"),
@Result(column = "age",property = "studentAge"),
@Result(column = "score",property = "studentScore"),
@Result(property = "accounts",column = "id",
many = @Many(select = "com.hcx.dao.AccountDao.findAccountByStudentId",fetchType = FetchType.LAZY))
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
复制代码
AccountDao:
public interface AccountDao {
/**
* 查询所有账户并获取每个账户所属用户信息
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "studentId",property = "studentId"),
@Result(column = "money",property = "money"),
@Result(property = "student",column = "studentId",one = @One(select = "com.hcx.dao.StudentDao.findById",
fetchType = FetchType.EAGER))
})
List<Account> findAll();
/**
* 根据学生id查询学生信息
* @param studentId
* @return
*/
@Select("select * from account where studentId=#{studentId}")
List<Account> findAccountByStudentId(Integer studentId);
}
复制代码
Test:
@Test
public void testFindAll(){
List<Student> students = studentDao.findAll();
for(Student student : students){
System.out.println(student);
}
}
复制代码
四、实现二级缓存
一级缓存:默认就开启:
@Test
public void testFindById(){
Student student = studentDao.findById(1);
System.out.println(student);
Student student1 = studentDao.findById(1);
System.out.println(student1);
//true
System.out.println(student==student1);
}
复制代码
在主配置文件中开启二级缓存(默认开启,不配置也可以) sqlMapConfig.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>
<!-- 引入外部配置文件-->
<properties resource="jdbcConfig.properties"></properties>
<!--设置开启二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置别名-->
<typeAliases>
<package name="com.hcx.domain"></package>
</typeAliases>
<!-- 配置环境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 指定带有注解的dao接口所在位置 -->
<mappers>
<!--<mapper class="com.hcx.dao.StudentDao"></mapper>-->
<package name="com.hcx.dao"></package>
</mappers>
</configuration>
复制代码
在mapper中使用注解@CacheNamespace(blocking=true)
@CacheNamespace(blocking = true)
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),
@Result(column = "name",property = "studentName"),
@Result(column = "age",property = "studentAge"),
@Result(column = "score",property = "studentScore"),
@Result(property = "accounts",column = "id",
many = @Many(select = "com.hcx.dao.AccountDao.findAccountByStudentId",fetchType = FetchType.LAZY))
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
复制代码
Test:
@Test
public void testFindOne(){
SqlSession sqlSession = factory.openSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.findById(1);
System.out.println(student);
sqlSession.close();
SqlSession sqlSession1 = factory.openSession();
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
Student student1 = studentDao1.findById(1);
System.out.println(student1);
sqlSession1.close();
//false
System.out.println(student==student1);
}
复制代码