mybatis多表查询的实现(xml方式)

作者:qq_42524262 时间:2021-07-11 01:21:38 

前言

表之间的关系有几种:一对多、多对一、 一对一、多对多
在多对一关系中,把多的部分拆成一个一个对象其实就是一对一关系,如账户和用户是多对一关系,但每个账户只对应一个用户。所以在mybatis中,多对一的关系可以看成一对一的关系。
这里我把一对多和多对一的xml配置方式总结了一下,同时还有加载方式。
一对多,多对多:通常情况下我们都是采用延迟加载。
多对一,一对一:通常情况下我们都是采用立即加载。
至于注解方式和多对多查询的xml和注解方式我会另外写博客。

数据库表及关系

我们以用户和账户为例,用户可以有多个账户,账户只能对应一个用户。所以用户对账户是一对多关系,账户对用户是多对一关系。表如下图所示,用户表user,账户表account,账户表UID对应用户表id。

mybatis多表查询的实现(xml方式)

mybatis多表查询的实现(xml方式)

一对多查询

首先我们要在User实体类中添加List accounts的集合成员变量,表示一对多映射关系,主表实体含有从表实体的集合引用。

public class User implements Serializable{
   private Integer id;
   private String username;
   private String address;
   private String sex;
   private Date birthday;

//一对多映射关系,主表实体含有从表实体的集合引用
   private List<Account> accounts;

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

public void setAccounts(List<Account> accounts) {
       this.accounts = accounts;
   }

@Override
   public String toString() {
       return "User{" +
               "id=" + id +
               ", username='" + username + '\'' +
               ", address='" + address + '\'' +
               ", sex='" + sex + '\'' +
               ", birthday=" + birthday +
               '}';
   }

public Integer getId() {
       return id;
   }

public void setId(Integer id) {
       this.id = id;
   }

public String getUsername() {
       return username;
   }

public void setUsername(String username) {
       this.username = username;
   }

public String getAddress() {
       return address;
   }

public void setAddress(String address) {
       this.address = address;
   }

public String getSex() {
       return sex;
   }

public void setSex(String sex) {
       this.sex = sex;
   }

public Date getBirthday() {
       return birthday;
   }

public void setBirthday(Date birthday) {
       this.birthday = birthday;
   }
}

同时在User Dao接口中提供查询所有方法findAll,在Account Dao接口中提供根据id查询user的方法findById,以便延时加载时调用。
这里说明因为用户可能对应许多账户,当我们查询用户时可能并不需要账户信息,而且如果我们每次查询用户时都立即查询用户的账户信息,并且账户信息有很多,势必对内存有很大的开销。所以当我们需要账户信息时再调用findById方法去查询用户对应的账户信息。

public interface IUserDao {
   /**
    * 查询所有操作,并携带账户信息
    * @return
    */
   List<User> findAll();

/**
    * 根据id查询一个用户
    * @param uid
    */
   User findById(Integer uid);

}
public interface IAccountDao {
   /**
    * 查询所有账户
    * @return
    */
   List<Account> findAll();

/**
    * 根据用户id查询账户
    * @param uid
    * @return
    */
   List<Account> findByUid(Integer uid);

}

然后配置userDao.xml,说明会在代码中给出。

<mapper namespace="com.cc.dao.IUserDao">
   <!--定义resultMap-->
   <!--因为在主配置文件中配置了domain包下的所有实体类别名,所以这里封装类型只需要写实体类名即可,不分大小写-->
   <resultMap id="userWithAccount" type="user">
       <!--封装user对象-->
       <id property="id" column="id"></id>
       <result property="username" column="username"></result>
       <result property="address" column="address"></result>
       <result property="sex" column="sex"></result>
       <result property="birthday" column="birthday"></result>
       <!--配置user队形中account集合的映射-->
       <!--定义一对多的关系映射,实现对account的封装,用collection标签
       ofType属性指定内容:要封装的实体对象类型
       select属性指定内容:查询用户的唯一标识
       column属性指定内容:用户根据id查询是所需要的参数
       -->
       <collection property="accounts" ofType="account" column="id" select="com.cc.dao.IAccountDao.findByUid"></collection>
   </resultMap>
   <!--查询所有-->
   <select id="findAll" resultMap="userWithAccount">
       select * from user
   </select>
   <!--根据id查询一个用户-->
   <select id="findById" parameterType="java.lang.Integer" resultType="user">
       select * from user where id=#{uid};
   </select>
</mapper>

当然我们还要在主配置文件中开启延时加载,默认情况下是立即加载。
lazyLoadingEnabled:是否启用延迟加载,mybatis默认为false,不启用延迟加载。lazyLoadingEnabled属性控制全局是否使用延迟加载,特殊关联关系也可以通过嵌套查询中fetchType属性单独配置(fetchType属性值lazy或者eager)。
也就是说我们可以不用在主配置文件中配置而在userDao.xml中配置,这里我们采用全局配置。

<!--配置参数-->
   <settings>
       <!--开启Mybatis支持延时加载-->
       <setting name="lazyLoadingEnabled" value="true"/>
       <setting name="aggressiveLazyLoading" value="false"></setting>
   </settings>
   <!--配置domain包下所有实体类别名-->
   <typeAliases>
       <!--<typeAlias type="com.cc.domain.User" alias="user"></typeAlias>-->
       <package name="com.cc.domain"></package>
   </typeAliases>

然后我们就可以测试了

public class UserTest {
   private InputStream in;
   private SqlSessionFactory factory;
   private SqlSession sqlSession;
   private IUserDao userDao;
   @Before//在测试方法执行之前执行
   public void init() throws IOException {
       //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
       //2.生成SqlSessionFactory
        factory = new SqlSessionFactoryBuilder().build(in);
       //3.获取SqlSession
        sqlSession = factory.openSession();
       //4.获取dao的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
   }
   @After//在测试方法执行之后执行
   public void destory() throws IOException {
       //提交事务
       sqlSession.commit();
       //关闭资源
       sqlSession.close();
       in.close();
   }

/**
    * 测试查询所有账户
    */
   @Test
   public void TestFindAll() {
       //5.执行查询所有方法
       List<User> userList = userDao.findAll();
      for (User user : userList) {
          System.out.println(user);
           System.out.println(user.getAccounts());
       }

}

}

先把遍历输出部分代码注释掉,测试可以看出我们只查询了用户信息。

mybatis多表查询的实现(xml方式)

然后去掉注释,发现当我们需要输出用户账户时,他就会去查询用户的账户信息。

mybatis多表查询的实现(xml方式)

多对一及一对一查询

步骤其实和一对多差不多。
首先我们在account实体类中加入user成员变量表示一对一映射。

public class Account implements Serializable {
   private Integer id;
   private Integer uid;
   private Double money;
   //从表实体应该包含一个主表实体的对象引用
   private User user;

public User getUser() {
       return user;
   }

public void setUser(User user) {
       this.user = user;
   }

public Integer getId() {
       return id;
   }

public void setId(Integer id) {
       this.id = id;
   }

public Integer getUid() {
       return uid;
   }

public void setUid(Integer uid) {
       this.uid = uid;
   }

public Double getMoney() {
       return money;
   }

public void setMoney(Double money) {
       this.money = money;
   }

@Override
   public String toString() {
       return "Account{" +
               "id=" + id +
               ", uid=" + uid +
               ", money=" + money +
               '}';
   }
}

Dao接口中需要的的方法在上面总结一对多查询时的图中已经给出。
然后配置accountDao.xml,这里是立即查询,在我们已经配置全局延时加载的情况下,我们需要配置fetchType=&ldquo;eager&rdquo;。

<mapper namespace="com.cc.dao.IAccountDao">
   <!--开启account支持二级缓存-->
   <cache/>
   <!--定义封装account和user的resultMap-->
   <resultMap id="accountAndUser" type="account">
       <id property="id" column="aid"></id>
       <result property="uid" column="uid"></result>
       <result property="money" column="money"></result>
       <!--定义一对一的关系映射,实现对user的封装
       select属性指定内容:查询用户的唯一标识
       column属性指定内容:用户根据id查询是所需要的参数
       fetchType属性指定内容:lazy延时加载,eager立即加载。
       -->
       <association property="user" column="uid" javaType="user" select="com.cc.dao.IUserDao.findById" fetchType="eager"></association>
   </resultMap>
   <!--查询所有-->
   <select id="findAll" resultMap="accountAndUser">
       SELECT * from account
   </select>
   <!--根据用户id查询-->
   <select id="findByUid" parameterType="java.lang.Integer" resultType="account" useCache="true">
       select * from account where uid = #{uid}
   </select>
</mapper>

然后我们就可以测试。可以看出当查询账户时就立即查询了对应的用户信息。

mybatis多表查询的实现(xml方式)

来源:https://blog.csdn.net/qq_42524262/article/details/97555275

标签:mybatis,多表查询
0
投稿

猜你喜欢

  • Java如何有效避免SQL注入漏洞的方法总结

    2021-11-22 07:01:54
  • jar包手动添加到本地maven仓库的步骤详解

    2023-11-23 05:09:37
  • SpringBoot框架集成ElasticSearch实现过程示例详解

    2023-02-02 08:44:05
  • SpringBoot使用Thymeleaf模板引擎访问静态html的过程

    2023-11-25 10:04:44
  • js+java实现登录滑动图片验证

    2022-02-21 21:17:17
  • java中Statement 与 PreparedStatement接口之间的关系和区别

    2023-11-25 03:11:11
  • spring mvc DispatcherServlet之前端控制器架构详解

    2023-07-30 16:53:23
  • Mybatis中的mapper模糊查询语句LIKE

    2022-02-17 16:21:15
  • 使用java为pdf添加书签的方法(pdf书签制作)

    2022-03-07 14:59:11
  • UGUI实现图片拖拽功能

    2021-06-27 18:26:24
  • Spring cloud config 配置文件加密方式

    2023-01-11 13:48:01
  • Java案例使用比较排序器comparator实现成绩排序

    2023-10-16 01:37:24
  • 深入了解Java核心类库--Math类

    2023-08-19 01:06:21
  • 解决WPF附加属性的Set函数不调用的问题

    2022-09-27 09:52:38
  • Springboot与Maven多环境配置的解决方案

    2023-11-29 08:53:58
  • java web服务器实现跨域访问

    2023-09-17 06:55:08
  • C# dump系统lsass内存和sam注册表详细

    2021-06-26 12:19:53
  • Android 之BottomsheetDialogFragment仿抖音评论底部弹出对话框效果(实例代码)

    2023-08-06 01:01:56
  • C# 4.0 大数的运算--BigInteger的应用详解

    2022-02-02 06:40:05
  • SpringBoot 如何从容器中获取对象

    2023-12-06 08:20:40
  • asp之家 软件编程 m.aspxhome.com