Mybatisマルチテーブルクエリ
- このケースでは、主にMybatisの複数テーブルの関係を、最も単純なユーザーおよびアカウントモデルと分析します。ユーザーはUserテーブルで、アカウントはAccountテーブルです。ユーザー(User)は複数のアカウント(Account)を持つことができます。具体的な関係は次のとおりです。
1対1のクエリ(多対1)
- 需要
- すべてのアカウント情報、関連するクエリユーザー情報をクエリします。
- 注:
- 1つのアカウント情報は特定のユーザーのみが使用できるため、アカウント情報のクエリからの関連するクエリユーザー情報は1対1のクエリです。ユーザー情報からユーザーアカウント情報をクエリする場合、ユーザーは複数のアカウントを持つことができるため、1対多のクエリです。
方法1
- アカウント情報を定義するエンティティクラス
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
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 + "]";
}
}
- AccountUserクラスを定義する
public class AccountUser extends Account implements Serializable {
private String username;
private String address;
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;
}
@Override
public String toString() {
return super.toString() + " AccountUser [username=" + username + ",
address=" + address + "]";
}
}
- SQLステートメントを書く
实现查询账户信息时,也要查询账户所对应的用户信息。
SELECT
account.*,
user.username,
user.address
FROM
account,
user
WHERE account.uid = user.id
- アカウントの永続化レイヤーのDaoインターフェースを定義する
public interface IAccountDao {
/**
* 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
* @return
*/
List<AccountUser> findAll();
}
- AccountDao.xmlファイルでクエリ構成情報を定義する
<mapper namespace="cn.myp666.dao.IAccountDao">
<!-- 配置查询所有操作-->
<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タイプに設定され、アカウント情報とユーザー情報を受け取ることができます。
- AccountTestテストクラスを作成する
@Test
public void testFindAll() {
//6.执行操作
List<AccountUser> accountusers = accountDao.findAll();
for(AccountUser au : accountusers) {
System.out.println(au);
}
- まとめ
- 特別なpoクラスを出力タイプとして定義します。これは、sqlクエリ結果セットのすべてのフィールドを定義します。この方法は比較的簡単で、企業で広く使用されています。
方法2
- resultMapを使用して、1対1のクエリ結果をマッピングするための特別なresultMapを定義します。
- オブジェクト指向の(ある)関係から、UserクラスのオブジェクトをAccountクラスに追加して、アカウントのどのユーザーを表すかを知ることができます。
- Accountクラスの変更
UserクラスオブジェクトをAccountクラスの属性としてAccountクラスに追加します。
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//添加User对象
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 + "]";
}
}
- AccountDaoインターフェースのメソッドを変更する
注:2番目の方法では、戻り値がAccountタイプに変更されます。AccountクラスにはUserクラスのオブジェクトが含まれているため、アカウントに対応するユーザー情報をカプセル化できます。
public interface IAccountDao {
/**
* 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
* @return
*/
List<Account> findAll();
}
- AccountDao.xmlファイルを再定義します
<mapper namespace="cn.myp666.dao.IAccountDao">
<!-- 建立对应关系 -->
<resultMap type="account" id="accountMap">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!-- 它是用于指定从表方的引用实体属性的 -->
<!--多对一的关系, property: 指的是属性的值, javaType:指的是属性的类型 -->
<association property="user" javaType="user">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findAll" resultMap="accountMap">
select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
</select>
</mapper>
- AccountTestクラスにテストメソッドを追加する
@Test
public void testFindAll() {
List<Account> accounts = accountDao.findAll();
for(Account au : accounts) {
System.out.println(au);
System.out.println(au.getUser());
}
}
1対多のクエリ
-
要件:
- すべてのユーザー情報とユーザー関連のアカウント情報をクエリします。
-
分析:
- ユーザー情報と彼のアカウント情報は1対多の関係にあり、クエリ中にユーザーがアカウント情報を持っていない場合は、この時点でユーザー情報もクエリする必要があります。左側の外部接続クエリがより適切であると考えました。
-
手順は次のとおりです。
- SQLステートメントを書く
SELECT
u.*,
acc.id as aid,
acc.uid,
acc.money
FROM
user u
LEFT JOIN account acc ON u.id = acc.uid
- リスト<アカウント>に追加されたユーザークラス
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
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 + "]";
}
}
- ユーザー永続性レイヤーのDaoインターフェースに追加されたクエリメソッド
List<User> findAll();
- ユーザー永続性レイヤーのDaoマッピングファイルの構成
<mapper namespace="cn.myp666.dao.IUserDao">
<resultMap type="user" id="userMap">
<id column="id" property="id"></id>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<!-- collection 是用于建立一对多中集合属性的对应关系
ofType 用于指定集合元素的数据类型
-->
<collection property="accounts" ofType="account">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
</collection>
</resultMap>
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
a on u.id =a.uid
</select>
</mapper>
- コレクション
セクションは、ユーザーに関連付けられたアカウント情報を定義します。関連するクエリ結果セット - property = "accounts":
Userオブジェクトのどのプロパティに、関連付けられたクエリの結果セットが格納されているか。 - ofType = "account":
関連するクエリの結果セット内のオブジェクトタイプ、つまりリスト内のオブジェクトタイプを指定します。ここでは、エイリアスまたは完全修飾名を使用できます。
- 試験方法
@Test
public void testFindAll() {
//6.执行操作
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println("-------每个用户的内容---------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}