从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

    • Redis

    • Mybatis

      • Mybatis介绍
      • Mybatis入门案例
      • Mybatis入门案例-注解
      • Mybatis入门案例-实现类
      • Mybatis内部执行原理概述
      • 实现一个微型的Mybatis-配置文件版
      • 实现一个微型的Mybatis-注解版
      • Mybatis实现CRUD
      • Mybatis中传递对象参数
      • Mybatis中的列名和属性名的映射
      • Mybatis实现DAO层的开发
      • Mybatis实现类的执行过程-查询方法
      • properties标签的使用及细节
      • typeAliases标签和package标签
      • Mybatis连接池和事务
      • Mybatis与JNDI
      • Mybatis中的动态SQL
      • Mybatis多表查询
      • Mybatis中的多对多查询
      • Mybatis的延迟加载
      • Mybatis的缓存
      • Mybatis的注解开发-CRUD
      • Mybatis的注解开发-多表查询
        • 注解建立成员变量和列名的映射
        • 一对一查询
        • 一对多查询
        • 缓存的配置
        • 源码
      • Mybatis
    • Lucene

    • Elasticsearch

    • MQ

    • MyCat

    • Lombok

    • 主流框架
  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • Java
  • 主流框架
  • Mybatis
2023-04-25
目录

Mybatis的注解开发-多表查询

# 210.Mybatis的注解开发-多表查询

来讲解更多使用注解完成开发的步骤。   ‍

# 注解建立成员变量和列名的映射

之前我们类的成员变量和数据库列名是一致的,所以不用映射;而使用注解也支持建立映射。

我们修改其成员变量的名字,和数据库列名不一致:

public class User implements Serializable {
    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
}
1
2
3
4
5
6
7

注:自行生成getter 和 setter。

‍

我们可以使用Results注解来完成映射。

@Select("select * from user")
@Results(value = {
        @Result(id=true, column = "id", property = "userId"),
        @Result(column = "username", property = "userName"),
        @Result(column = "address", property = "userAddress"),
        @Result(column = "sex", property = "userSex"),
        @Result(column = "birthday", property = "userBirthday")
})
List<User> findAll();
1
2
3
4
5
6
7
8
9

‍

再次运行findAll方法,可以看到正常运行。

‍

那么其他CRUD注解还需要自己写一份Results注解吗?不用的,我们可以给Result定义一个id,然后其他注解可以应用这个ID:

@Select("select * from user")
@Results(id = "userMap", value = {
        @Result(id=true, column = "id", property = "userId"),
        @Result(column = "username", property = "userName"),
        @Result(column = "address", property = "userAddress"),
        @Result(column = "sex", property = "userSex"),
        @Result(column = "birthday", property = "userBirthday")
})
List<User> findAll();
1
2
3
4
5
6
7
8
9

‍

其他注解就可以使用ResultMap来指定:注意ResultMap可以写多个,这里我们只用到了一个

@Select("select * from user where id=#{id}")
@ResultMap("userMap")
User findById(Integer id);
1
2
3

‍

‍

‍

# 一对一查询

我们试着在查询账户的时候,同时查询用户信息,

新建Account类:

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
}
1
2
3
4
5

请读者自行生成 setter 和 getter。

‍

新增IAccountDao.java​接口

public interface IAccountDao {
    @Select("select * from account")
    List<Account> findAll();
}
1
2
3
4

‍

新建测试类AccountAnnoTest:

@Test
public void testFindAll(){
    List<Account> accounts = iAccountDao.findAll();
    for(Account account : accounts){
        System.out.println(account);
    }
}
1
2
3
4
5
6
7

可以正常打印;

‍

‍

新增User成员变量:

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;

    // 多对一(在Mybatis称为一对一)的映射
    private User user;
}
1
2
3
4
5
6
7
8

‍

修改findAll方法:

@Select("select * from account")
@Results(id = "accountMap", value = {
        @Result(id = true, column = "id", property = "id"),
        @Result(column = "uid", property = "uid"),
        @Result(column = "money", property = "money"),
        @Result(column = "uid", property = "user", one = @One(select = "com.peterjxl.dao.IUserDao.findById", fetchType= FetchType.EAGER) )
})
List<Account> findAll();
1
2
3
4
5
6
7
8

one表示一对一查询,selet属性则是根据某个方法来查询,fetchType表示延迟加载还是立即加载

‍

修改测试方法:

@Test
public void testFindAll(){
    List<Account> accounts = iAccountDao.findAll();
    for(Account account : accounts){
        System.out.print(account);
        System.out.println(account.getUser());
    }
}
1
2
3
4
5
6
7
8

‍

可以看到能正常查询:

​​

‍

‍

# 一对多查询

我们试着在查询用户的时候,查询其所有账户,也就是一对多

‍

我们先在IAcountDao接口中新建方法:findAccountByUid

/**
 * 根据用户ID查询账户
 * @param uid
 * @return
 */
@Select("select * from account where uid = #{userId}")
List<Account> findAccountByUid(Integer uid);
1
2
3
4
5
6
7

‍

‍

我们在User类中新建Account属性:

// 一对多关系映射,一个用户对应多个账户
private List<Account> accounts;

public List<Account> getAccounts() {
    return accounts;
}

public void setAccounts(List<Account> accounts) {
    this.accounts = accounts;
}
1
2
3
4
5
6
7
8
9
10

‍

然后在IUserDao中增加一对多查询配置:这里我们选择懒加载,关键是第9行









 



@Select("select * from user")
@Results(id = "userMap", value = {
        @Result(id=true, column = "id", property = "userId"),
        @Result(column = "username", property = "userName"),
        @Result(column = "address", property = "userAddress"),
        @Result(column = "sex", property = "userSex"),
        @Result(column = "birthday", property = "userBirthday"),
        @Result(column = "id", property = "accounts", 
                many = @Many(select = "com.peterjxl.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY))
})
List<User> findAll();
1
2
3
4
5
6
7
8
9
10
11

‍

修改测试方法:

@Test
public void testFindAll(){
    List<User> users = userDao.findAll();
    for(User user : users){
        System.out.print(user);
        System.out.println(user.getAccounts());
    }
}
1
2
3
4
5
6
7
8

‍

‍

可以看到,能正常查询,并且是延迟加载的模式

​​

‍

# 缓存的配置

‍

我们修改测试方法,看看有无一级缓存:

@Test
public void testFindOne(){
    User user = userDao.findById(41);
    System.out.println(user);

    User user2 = userDao.findById(41);
    System.out.println(user2);
  
    System.out.println( "user == user2 ? " + (user == user2));
}
1
2
3
4
5
6
7
8
9
10

‍

运行结果:可以看到,一级缓存是存在的。

user == user2 ? true
1

‍

我们新建一个测试类

public class SecondLevelCatchTest {
    private InputStream in;
    private SqlSessionFactory factory;

    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
    }

    @After
    public void destroy() throws IOException {
        in.close();
    }

    @Test
    public void testFindOne(){
        SqlSession session = factory.openSession();
        IUserDao userDao = session.getMapper(IUserDao.class);
        User user = userDao.findById(41);
        System.out.println(user);
        session.close();    //释放一级缓存
    
        SqlSession session1 = factory.openSession();    //再次打开session
        IUserDao userDao1 = session1.getMapper(IUserDao.class);
        User user1 = userDao1.findById(41);
        System.out.println(user1);
        session1.close();
    }
}
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

‍

可以看到testFindOne会查询两次查询,因为我们没有配置二级缓存:

​​​​

‍

‍

我们在IUserDao接口上,加一个注解即可开启二级缓存:blocking默认是false,我们改成true

@CacheNamespace(blocking = true)
public interface IUserDao {
1
2

‍

可以看到值查询了一次

​

​

# 源码

所有代码已上传到了GitHub (opens new window)和Gitee (opens new window)上,并且创建了分支demo20,读者可以通过切换分支来查看本文的示例代码。

在GitHub上编辑此页 (opens new window)
上次更新: 2023/5/15 16:02:46
Mybatis的注解开发-CRUD
Mybatis

← Mybatis的注解开发-CRUD Mybatis→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式