Mybatis学习第七弹。
Mybatis-7-注解开发
注解开发可以减少xml配置文件的编写。
1. Mybatis中常用的注解
@Insert:新增操作
@Update:更新操作
@Delete:删除操作
@Select:查询操作
@Result:结果集的封装
@Results:与Result一起使用,实现多个结果集封装
@ResultMap:实现引用@Results定义的封装
@One:一对一的结果集封装
@Many:一对多结果集封装
@SelectProvider:动态SQL映射
@CacheNamespace:二级缓存配置
2. 注解开发入门
- 根据数据库表封装实体类
- 使用注解方式开发持久层接口
- 修改SqlMapConfig.xml配置文件
- 测试
1. 根据数据库封装实体类
封装User表
1 | public class User implements Serializable { |
2. 使用注解方式开发持久层接口
- 把resources下xml配置文件删除
- 把SqlMapConfig下的mappers下的Mapper引用改为持久层接口的全限定类名。
- 使用注解开发
更改mapper
1
2
3<mappers>
<mapper class="top.tobing.dao.UserDao"></mapper>
</mappers>注解开发
根据id查询数据
1
2
3
4public interface UserDao {
public User findById(int id);
}
3. 测试
检验注解开发是否能够正常查询出来数据
1 |
|
结果:User{id=44, username=’CacheTest’, birthday=null, sex=’男’, address=’英国’}
3. 使用注解实现简单CRUD
- 使用注解开发实现简单的CRUD
- 使用注解配置:数据库列名和实体类属性名的一一对应(非常规)
创建实体类
此处故意使得实体类属性名和数据库列名不匹配
1
2
3
4
5
6
7
8public class User implements Serializable {
// 对应数据库的列名
private int userId; // ===>id
private String userName; // ===>username
private Date userBirthday; // ===>birthday
private String userSex; // ===>sex
private String userAddress; // ===>address
}在UserDao中添加用于对User进行CRUD的抽象方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public interface UserDao {
// 查询所有用户
public List<User> findAll();
// 更加Id查询用户
// 使用userMap封装
public User findById(Integer id);
// 保存用户信息
public int saveUser(User user);
// 更新用户信息
public int updateUser(User user);
// 查询总记录数
public int findTotal();
// 根据用户名模糊查询
// 使用userMap封装
public List<User> findByName(String username);
}- 此处由于数据库列名和实体类的字段名不对应,需要通过使用注解@Results和@Result来建立数据库列名和实体类字段名的一一对应关系。
- 在需要封装结果集的地方使用注解@ResultMap引用自定义的封装。
测试建议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82public class UserDaoTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
public void init(){
try {
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建工厂类
factory =new SqlSessionFactoryBuilder().build(in);
//3.生产SqlSession对象
session = factory.openSession();
//4.获取代理对象
userDao = session.getMapper(UserDao.class);
} catch (IOException e) {
e.printStackTrace();
}
}
public void destory() throws IOException {
session.commit();
session.close();
in.close();
}
public void findByIdTest(){
User user = userDao.findById(44);
System.out.println(user);
}
// 查询所有用户
public void findAllTest() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
// 保存用户信息
public void saveUser() {
User u = new User();
u.setUserAddress("水帘洞");
u.setUserBirthday(new Date());
u.setUserName("孙悟空");
u.setUserSex("男");
int res = userDao.saveUser(u);
System.out.println(res);
}
// 更新用户信息
public void updateUser(){
User u = new User();
u.setUserName("孙悟饭");
u.setUserAddress("水帘洞");
u.setUserBirthday(new Date());
u.setUserSex("男");
u.setUserId(47);
int res = userDao.updateUser(u);
System.out.println(res);
}
// 查询总记录数
public void findTotal(){
int total = userDao.findTotal();
System.out.println(total);
}
// 根据用户名模糊查询
public void findByName(){
List<User> users = userDao.findByName("%张%");
for (User user : users) {
System.out.println(user);
}
}
}
4. 使用注解查询复杂关系
1. 注解说明
1 |
Results
1
2
3
4public Results {
String id() default ""; // 指定主键
Result[] value() default {}; // 指定类名和属性的对应关系(Result注解)
}Result
1
2
3
4
5
6
7
8
9
10
11public Result {
boolean id() default false; // 是否为主键
String column() default ""; // 数据库列名
String property() default ""; // 实体类属性名
One one() default @One; // 使用@One注解
Many many() default @Many; // 使用@Many注解
}One
1
2
3
4
5public One {
String select() default ""; // 指定用于多表查询的sqlMapper
// 覆盖全局的配置参数lazyLoadingEnable
FetchType fetchType() default FetchType.DEFAULT;
}Many
1
2
3
4
5public Many {
String select() default ""; // 指定用于多表查询的sqlMapper
FetchType fetchType() default FetchType.DEFAULT;
}总结
@One
指定一对一
代替了<assocation>标签,是多表查询的关键。
用于指定查询返回单一对象
@Many
- 指定一对多
- 代替了<Collection>,是多表查询的关键
- 用于指定查询返回集合对象
2. 使用注解开发一对一的复制关系映射
需求:加载账号时,加载用户信息。(可根据情况延迟加载)
创建Account类和User类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// Account类
public class Account implements Serializable {
private int id;
private int uid;
private double money;
private User user; // 与账号一一对应的用户
}
// User类
public class User implements Serializable {
private int userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
private List<Account> accounts;
}
添加Account持久层dao并使用注解配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public interface AccountDao {
List<Account> findAll(); // 查询所有方法
}
添加User持久层dao并使用注解配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public interface UserDao {
// 查询所有用户
public List<User> findAll();
// 更加Id查询用户
// 使用userMap封装
public User findById(Integer id);
}
测试数据
1
2
3
4
5
6
7
8
9
public void findAllTest(){
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println("-------------------------");
System.out.println(account);
System.out.println(account.getUser());
}
}
测试延迟加载
1
2
3
4
5
6
7
8
9
public void lazyLoadingTest(){
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println(account.getMoney());
System.out.println(account.getId());
}
}
3. 使用注解开发一对多的复杂关系映射
需求:查询用户信息,按需查询其账号信息。(延迟加载)
User中加入List<Account>
编写User持久层接口并使用注解配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public interface UserDao {
// 查询所有用户
public List<User> findAll();
}
编写Account持久层接口并使用注解配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public interface AccountDao {
List<Account> findAll();
List<Account> findByUid();
}
添加测试方法
1
2
3
4
5
6
7
public void findAllTest() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user.getUserName());
}
}
5. 注解实现开启二级缓存
1. SqlMapConfig配置
1 | <configuration > |
2. 持久层注解开启二级缓存
1 |
|