1. 程式人生 > 實用技巧 >mybatis一對一查詢(多對一)

mybatis一對一查詢(多對一)

mybatis一對一查詢(多對一)

需求:查詢所有賬戶資訊,關聯查詢使用者資訊。

注意:因為一個賬戶資訊只能供某個使用者使用,所以從查詢賬戶資訊出發關聯查詢使用者資訊為一對一查詢。如果從使用者資訊出發查詢使用者下的賬戶資訊則為一對多查詢,因為一個使用者可以有多個賬戶。

1、方式一

1.1、賬戶資訊實體類

package com.yl.bean;

import java.io.Serializable;

/**
 * 賬戶實體類
 */
public class Account implements Serializable {
    private Integer id;//賬戶id
    private Integer uid;//使用者id
    private Double money;//餘額

    public Account() {
    }

    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 +
                '}';
    }
}

1.2、使用者實體類

package com.yl.bean;

import java.io.Serializable;
import java.sql.Date;

/**
 * 使用者實體類
 */
public class User implements Serializable {
    private Integer id;//id
    private String username;//使用者名稱
    private Date birthday;//生日
    private String sex;//性別
    private String address;//地址

    public User() {
    }

    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 Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

1.3、編寫sql語句

//實現查詢賬戶資訊時,也要查詢賬戶所對應的使用者資訊。
SELECT 
 account.*,
 user.username,
 user.address
FROM
 account,
 user
WHERE account.uid = user.id

1.4、定義AccountUser類

為了能夠封裝上面 SQL 語句的查詢結果,定義 AccountCustomer 類中要包含賬戶資訊同時還要包含使用者資訊,所以我們要在定義 AccountUser 類時可以繼承 User 類。

package com.yl.bean;

public class AccountUser extends User{
    private String username;//使用者名稱
    private String address;//地址

    @Override
    public String getUsername() {
        return username;
    }

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

    @Override
    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return super.toString()+"AccountUser{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}


1.5、定義賬戶持久層介面

package com.yl.dao;

import com.yl.bean.Account;
import com.yl.bean.User;

import java.util.List;

/**
 * 賬戶持久層介面
 */
public interface IAccountDao {

    /**
     * 查詢所有賬戶
     */
    List<AccountUser> queryAll();
}

1.6、配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper 
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.IAccountDao">
	<!-- 配置查詢所有操作,resultType使用了別名-->
    <select id="findAll" resultType="accountuser">
		select a.*,u.username,u.address from account a,user u where a.uid =u.id;
	</select>
</mapper>

注意:因為上面查詢的結果中包含了賬戶資訊同時還包含了使用者資訊,所以我們的返回值型別 returnType的值設定為 AccountUser 型別,這樣就可以接收賬戶資訊和使用者資訊了。

1.7、測試

@Test
public void testFindAll() {
    List<AccountUser> accountusers = accountDao.findAll();
    for(AccountUser au : accountusers) {
        System.out.println(au);
	} 
}

1.8、小結

定義專門的 po 類作為輸出型別,其中定義了 sql 查詢結果集所有的欄位。此方法較為簡單,企業中使用普遍。

2、方式二

使用 resultMap,定義專門的 resultMap 用於對映一對一查詢結果。通過面向物件的(has a)關係可以得知,我們可以在 Account 類中加入一個 User 類的物件來代表這個賬戶是哪個使用者的。

2.1、修改賬戶資訊實體類

package com.yl.bean;

import java.io.Serializable;

/**
 * 賬戶實體類
 */
public class Account implements Serializable {
    private Integer id;//賬戶id
    private Integer uid;//使用者id
    private Double money;//餘額
    private User user;//賬戶所屬使用者

    public Account() {
    }

    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;
    }

    public User getUser() {
        return user;
    }

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

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

2.2、使用者實體類

package com.yl.bean;

import java.io.Serializable;
import java.sql.Date;

/**
 * 使用者實體類
 */
public class User implements Serializable {
    private Integer id;//id
    private String username;//使用者名稱
    private Date birthday;//生日
    private String sex;//性別
    private String address;//地址

    public User() {
    }

    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 Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

2.3、賬戶持久層介面

package com.yl.dao;

import com.yl.bean.Account;
import com.yl.bean.User;

import java.util.List;

/**
 * 賬戶持久層介面
 */
public interface IAccountDao {

    /**
     * 查詢所有賬戶
     */
    List<Account> queryAll();
}

注意:第二種方式,將返回值改 為了 Account 型別。因為 Account 類中包含了一個 User 類的物件,它可以封裝賬戶所對應的使用者資訊。

2.4、配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.yl.dao.IAccountDao">
    <!--配置Account屬性對應資料庫資訊-->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--一對一關係對映,javaType使用了別名-->
        <association property="user" column="uid" javaType="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
    
    <!--查詢所有賬戶-->
    <select id="queryAll" resultMap="accountUserMap">
        SELECT * FROM USER u,account a WHERE u.`id`=a.`UID`
    </select>
</mapper>

2.5、測試

package com.yl;

import com.yl.bean.Account;
import com.yl.bean.User;
import com.yl.dao.IAccountDao;
import com.yl.dao.IUserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Date;
import java.util.List;


public class AccountTest {
    private InputStream inputStream;
    private IAccountDao accountDao;
    private SqlSession sqlSession;

    @Before
    public void init() throws IOException {
        //讀取配置檔案
        inputStream= Resources.getResourceAsStream("SqlMapperConfig.xml");
        //建立工廠
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory= factoryBuilder.build(inputStream);
        //建立SqlSession物件
        sqlSession=sessionFactory.openSession();
        //建立IUserDao介面代理物件
        accountDao=sqlSession.getMapper(IAccountDao.class);
    }

    @After
    public void after() throws IOException {
        //提交事務
        sqlSession.commit();;
        //關閉資源
        sqlSession.close();
        inputStream.close();
    }

    /**
     * 查詢所有
     */
    @Test
    public void test01() throws IOException {
        //查詢所有賬戶
        List<Account> accountList=accountDao.queryAll();
        //遍歷輸出
        for (Account account:accountList){
            System.out.println(account);
            System.out.println(account.getUser().toString());
        }
    }

}