对应的四种数据库表关系中存在四种关系:一对多,多对应,一对一,多对多。在前文中已经实现了xml配置方式实现表关系的查询,本文记录一下Mybatis怎么通过注解实现多表的查询,算是一个知识的补充。

  同样的先介绍一下Demo的情况:存在两个实体类用户类和账户类,用户类可能存在多个账户,即一对多的表关系。每个账户只能属于一个用户,即一对一或者多对一关系。我们最后实现两个方法,第一个实现查询所有用户信息并同时查询出每个用户的账户信息,第二个实现查询所有的账户信息并且同时查询出其所属的用户信息。

  1.项目结构

  

  2.领域类

public class Account implements Serializable{
private Integer id;
private Integer uid;
private double money;
private User user; //加入所属用户的属性
省略get 和set 方法.............................
} public class User implements Serializable{
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
private List<Account> accounts;
省略get 和set 方法.............................
}

  在User中因为一个用户有多个账户所以添加Account的列表,在Account中因为一个账户只能属于一个User,所以添加User的对象。 

  3.Dao层

 public interface AccountDao {
/**
*查询所有账户并同时查询出所属账户信息
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,property = "id",column = "id"),
@Result(property = "uid",column = "uid"),
@Result(property = "money",column = "money"),
//配置用户查询的方式 column代表的传入的字段,一对一查询用one select 代表使用的方法的全限定名, fetchType表示查询的方式为立即加载还是懒加载
@Result(property = "user",column = "uid",one = @One(select = "com.example.dao.UserDao.findById",fetchType = FetchType.EAGER))
})
List<Account> findAll(); /**
* 根据用户ID查询所有账户
* @param id
* @return
*/
@Select("select * from account where uid = #{id}")
List<Account> findAccountByUid(Integer id);
} public interface UserDao {
/**
* 查找所有用户
* @return
*/
@Select("select * from User")
@Results(id = "userMap",value = {@Result(id = true,column = "id",property = "userId"),
@Result(column = "username",property = "userName"),
@Result(column = "birthday",property = "userBirthday"),
@Result(column = "sex",property = "userSex"),
@Result(column = "address",property = "userAddress"),
@Result(column = "id",property = "accounts",many = @Many(select = "com.example.dao.AccountDao.findAccountByUid",fetchType = FetchType.LAZY))
})
List<User> findAll(); /**
* 保存用户
* @param user
*/
@Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
void saveUser(User user); /**
* 更新用户
* @param user
*/
@Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}")
void updateUser(User user); /**
* 删除用户
* @param id
*/
@Delete("delete from user where id=#{id}")
void deleteUser(Integer id); /**
* 查询用户根据ID
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
@ResultMap(value = {"userMap"})
User findById(Integer id); /**
* 根据用户名称查询用户
* @param name
* @return
*/
// @Select("select * from user where username like #{name}")
@Select("select * from user where username like '%${value}%'")
List<User> findByUserName(String name); /**
* 查询用户数量
* @return
*/
@Select("select count(*) from user")
int findTotalUser();

  在findAll()方法中配置@Results的返回值的注解,在@Results注解中使用@Result配置根据用户和账户的关系而添加的属性,User中的属性List<Account>一个用户有多个账户的关系的映射配置:@Result(column = "id",property = "accounts",many = @Many(select = "com.example.dao.AccountDao.findAccountByUid",fetchType = FetchType.LAZY)),使用@Many来向Mybatis表明其一对多的关系,@Many中的select属性对应的AccountDao中的findAccountByUid方法的全限定名,fetchType代表使用立即加载或者延迟加载,因为这里为一对多根据前面的讲解,懒加载的使用方式介绍一对多关系一般使用延迟加载,所以这里配置为LAZY方式。在Account中存在多对一或者一对一关系,所以配置返回值属性时使用:@Result(property = "user",column = "uid",one = @One(select = "com.example.dao.UserDao.findById",fetchType = FetchType.EAGER)),property代表领域类中声明的属性,column代表传入后面select语句中的参数,因为这里为一对一或者说为多对一,所以使用@One注解来描述其关系,EAGER表示使用立即加载的方式,select代表查询本条数据时所用的方法的全限定名,fetchType代表使用立即加载还是延迟加载。

  4.Demo中Mybatis的配置

<?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>
<settings>
<!--&lt;!&ndash;开启全局的懒加载&ndash;&gt;-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--&lt;!&ndash;关闭立即加载,其实不用配置,默认为false&ndash;&gt;-->
<!--<setting name="aggressiveLazyLoading" value="false"/>-->
<!--开启Mybatis的sql执行相关信息打印-->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--<setting name="cacheEnabled" value="true"/>-->
</settings>
<typeAliases>
<typeAlias type="com.example.domain.User" alias="user"/>
<package name="com.example.domain"/>
</typeAliases>
<environments default="test">
<environment id="test">
<!--配置事务-->
<transactionManager type="jdbc"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test1"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.example.dao"/>
</mappers>
</configuration>

  主要是记得开启mybatis中sql执行情况的打印,方便我们查看执行情况。

  5.测试

  (1)测试查询用户同时查询出其账户的信息

   测试代码:

public class UserTest {

    private InputStream in;
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private UserDao userDao;
@Before
public void init()throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destory()throws Exception{
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
List<User> userList = userDao.findAll();
for (User user: userList){
System.out.println("每个用户信息");
System.out.println(user);
System.out.println(user.getAccounts());
}
}

  测试结果:

(2)查询所有账户信息同时查询出其所属的用户信息

  测试代码:

public class AccountTest {

    private InputStream in;
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private AccountDao accountDao;
@Before
public void init()throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
sqlSession = sqlSessionFactory.openSession();
accountDao = sqlSession.getMapper(AccountDao.class);
}
@After
public void destory()throws Exception{
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
List<Account> accountList = accountDao.findAll();
for (Account account: accountList){
System.out.println("查询的每个账户");
System.out.println(account);
System.out.println(account.getUser());
}
}
}

测试结果:

Mybatis基于注解实现多表查询的更多相关文章

  1. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  2. django之 使用views.py里面的函数对表进行增删改查 内容(models.py中表的创建、views.py中函数的使用,基于对象的跨表查询)

    models之对于表的创建有以下几种: 一对一:ForeignKey("Author",unique=True),  OneToOneField("Author" ...

  3. python 全栈开发,Day73(django多表添加,基于对象的跨表查询)

    昨日内容回顾 多表方案: 如何确定表关系呢? 表关系是在2张表之间建立的,没有超过2个表的情况. 那么相互之间有2条关系线,先来判断一对多的关系. 如果其中一张表的记录能够对应另外一张表的多条记录,那 ...

  4. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  5. 基于对象的跨表查询,多对多查询,多对多操作,聚合查询和分组查询,F查询和Q 查询

    基于对象的跨表查询 一对多查询(班级表和学生表) 表结构创建 class Class(models.Model): id = models.AutoField(primary_key=True) cn ...

  6. Django day08 多表操作 (三) 基于对象的跨表查询 基于双下划线的多表查询

    一: 基于对象的跨表查询 1. 一对一 正向: 反向: 2. 一对多 正向: 反向: 3.多对多 正向: 反向: 4.*****基于对象的多表查询 二: 基于双下划线的多表查询 1. 连表查询 一对一 ...

  7. day61——多表操作(增、删除、改、基于对象的跨表查询)

    day61 增删改查 增加 # 增加 # 一对一 # au_obj = models.AuthorDetail.objects.get(id=4) models.Author.objects.crea ...

  8. 五、Django学习之基于对象的跨表查询

    五.Django学习之基于对象的跨表查询 正向与反向查询 关键在于ForeignKey字段写的位置.例如下面这段代码, 关系属性(字段)写在哪个类(表)里面,从当前类(表)的数据去查询它关联类(表)的 ...

  9. mybatis进阶案例之多表查询

    mybatis进阶案例之多表查询 一.mybatis中表之间的关系 在数据库中,实体型之间的关系主要有如下几种: 1.一对一 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之 ...

随机推荐

  1. 0728 history

    -- :: cd /etc/yum.repos.d/ -- :: wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox. ...

  2. Android的简述

    程序截图 先来简单了解下程序运行的效果 程序入口点  类似于win32程序里的WinMain函数,Android自然也有它的程序入口点.它通过在AndroidManifest.xml文件中配置来指明, ...

  3. JS原生隐士标签扩展

    最近项目开发中,开发了不少的接口,有一个接口是这样子的.先从A公司拿到数据后,存放到我们公司数据库里,然后需要将数据展示给客户,下面这个界面,后台要实时刷新,后台写了个定时器,2S刷一次从后台拼接好H ...

  4. VisualStudio中的单元测试

    1. VisualStuio中的测试资源管理器.CodeLens和ReSharper 上一篇文章重温了<单元测试的艺术>里提到的单元测试的技术及原则.这篇文章实践使用VisualStudi ...

  5. 一文掌握 Spring Boot Profiles

    Spring Boot Profiles 简介 Profile 的概念其实很早在 Spring Framework 就有了,在 Spring Framework 3.1 版本引入了注解 @Profil ...

  6. 林大妈的JavaScript基础知识(三):JavaScript编程(2)函数

    JavaScript是一门函数式的面向对象编程语言.了解函数将会是了解对象创建和操作.原型及原型方法.模块化编程等的重要基础.函数包含一组语句,它的主要功能是代码复用.隐藏信息和组合调用.我们编程就是 ...

  7. 多线程编程(Linux C)

    多线程编程可以说每个程序员的基本功,同时也是开发中的难点之一,本文以Linux C为例,讲述了线程的创建及常用的几种线程同步的方式,最后对多线程编程进行了总结与思考并给出代码示例. 一.创建线程 多线 ...

  8. Linux下zookeeper下载与安装教程

    原文连接:(http://www.studyshare.cn/blog-front//blog/details/1169/0)一.下载 官网下载:点这里  百度网盘下载:点这里 官网下载图示: jav ...

  9. Mysql之锁、事务绝版详解---干货!

    一 锁的分类及特性 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能 ...

  10. c#小灶——标识符和关键字

    标识符 我们之前说,命名空间的名字是自己取的,类名也是自己取的,方法名也是自己取的,以后还有各种常量.变量.对象……这些名字是自己取的.这些名字,就是标识符. 标识符规则: 标识符可以包含大小写字母. ...