目錄
mybatis關聯查詢(一對多和多對一)
1 創建DBUtils工具類
public class DBUtils {
private static SqlSessionFactory factory = null;
static {
try {
String mybatis_config = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(mybatis_config);
factory = new SqlSessionFactoryBuilder().build(in);
} catch (Exception e) {
e.printStackTrace();
}
}
// 獲取SqlSession
public static SqlSession getSqlSession() {
return factory.openSession(true);
}
// 獲取mapper
public static <T> T getMapper(Class<T> mapper) {
return getSqlSession().getMapper(mapper);
}
}
2 准備數據
用戶和賬戶兩個表
用戶表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
`address` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
賬戶表
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`id` int(11) NOT NULL,
`uid` int(11) DEFAULT NULL COMMENT '用戶id',
`money` double(20, 0) DEFAULT NULL COMMENT '賬戶余額',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
插入用戶數據
INSERT INTO `user` VALUES (1, '張三', 18, '河北');
INSERT INTO `user` VALUES (2, '李四', 29, '北京');
INSERT INTO `user` VALUES (3, '王五', 30, '天津');
INSERT INTO `user` VALUES (4, '趙六', 28, '廣州');
INSERT INTO `user` VALUES (5, '楊七', 88, '上海');
插入賬戶數據
INSERT INTO `account` VALUES (1, 1, 1000);
INSERT INTO `account` VALUES (2, 1, 3000);
INSERT INTO `account` VALUES (3, 3, 5000);
3 mybatis一對多查詢
ResultMap格式:
<resultMap id="唯一的標識" type="映射的pojo對象">
<id column="表的主鍵字段(數據庫表中的字段)" jdbcType="字段類型" property="映射pojo對象的主鍵屬性(實體類中的屬性)" />
<result column="表字段名或者別名(定義別名后不是能原來的字段名)" jdbcType="字段類型" property="映射到pojo對象的一個屬性(實體類中的屬性)"/>
<!--多個標簽<result>...-->
<!-- 一對多用collection標簽-->
<collection property="pojo的集合屬性名(實體類中多的一方的集合)" ofType="集合中的pojo對象的類型">
<id column="主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />
<result column="表字段名或者別名" jdbcType="字段類型" property="集合中的pojo對象的屬性" />
<!--多個標簽<result>...-->
</collection>
</resultMap>
案例
一個用戶可以有多個賬戶, 查詢所有的用戶,
用戶類
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private Integer age;
private String address;
//一對多映射集合
private List<Account> accounts;
}
賬戶類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private Integer id;
private Integer uid;
private Double money;
}
實現UserMapper接口
public interface UserMapper {
List<User> findAllUser();
}
方案一:聯表查詢(按照結果嵌套處理)
<mapper namespace="com.tedu.dao.UserMapper">
<resultMap id="userAccountMap" type="user">
<id column="uid" property="id"/>
<result column="uname" property="name"/>
<result column="uage" property="age"/>
<result column="uaddress" property="address"/>
<collection property="accounts" javaType="ArrayList" ofType="Account">
<id column="aid" property="id"/>
<result column="auid" property="uid"/>
<result column="amoney" property="money"/>
</collection>
</resultMap>
<select id="findAllUser" resultMap="userAccountMap">
select
u.id uid,
u.name uname,
u.age uage,
u.address uaddress,
a.id aid,
a.uid auid,
a.money amoney
from user u
left join account a
on u.id =a.uid;
</select>
方案二: 按查詢嵌套處理
<select id="findAllUser" resultMap="userAccountMap">
select * from user
</select>
<select id="findAccountById" resultType="Account">
select * from account where uid =#{id}
</select>
<resultMap id="userAccountMap" type="user">
<!-- 數據庫的字段名和pojo對象中的屬性名一致,可以不用映射,但是要再次基於id執行嵌套查詢,則需將id表明.將查詢結果封裝-->
<id property="id" column="id"/>
<collection column="id" property="accounts" ofType="Account" javaType="ArrayList" select="findAccountById"/>
</resultMap>
方案一二測試如下
// 查詢所有的用戶
@Test
public void test1() {
UserMapper mapper = DBUtil.getMapper(UserMapper.class);
List<User> allUser = mapper.findAllUser();
for (User user : allUser) {
System.out.println(user.getId()+","+user.getName()+","+user.getAddress()+","+user.getAge());
System.out.println(user.getAccounts());
}
}
測試結果如下:
1,張三,河北,18
[Account(id=1, uid=1, money=1000.0, user=null), Account(id=2, uid=1, money=3000.0, user=null)]
2,李四,北京,29
[]
3,王五,天津,30
[Account(id=3, uid=3, money=5000.0, user=null)]
4,趙六,廣州,28
[]
5,楊七,上海,88
[]
4 mybatis多對一查詢
resultMap格式:
<resultMap id="唯一的標識" type="映射的pojo對象">
<id column="表的主鍵字段" jdbcType="字段類型" property="映射pojo對象的主鍵屬性" />
<result column="表字段名或者別名" jdbcType="字段類型" property="映射到pojo對象的一個屬性"/>
<!--多個標簽<result>...-->
<association property="pojo的對象屬性名" javaType="引用配型">
<id column="主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />
<result column="表字段名或者別名" jdbcType="字段類型" property="集合中的pojo對象的屬性" />
<!--多個標簽<result>...-->
</association>
</resultMap>
案例
用戶類
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private Integer age;
private String address;
}
賬戶類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private Integer id;
private Integer uid;
private Double money;
//多對一映射
private User user;
}
AccountMapper類
//查詢每個賬戶所對應的用戶
public interface AccountMapper {
List<Account> findAllAccount();
}
方案一:按照結果處理
<mapper namespace="com.tedu.dao.AccountMapper">
<resultMap id="accountUserMap" type="Account">
<id column="aid" property="id"/>
<result column="auid" property="uid"/>
<result column="amoney" property="money"/>
<association property="user" javaType="User">
<id column="uid" property="id"/>
<result column="uname" property="name"/>
<result column="uage" property="age"/>
<result column="uaddress" property="address"/>
</association>
</resultMap>
<select id="findAllAccount" resultMap="accountUserMap">
select
a.id aid,
a.uid auid,
a.money amoney,
u.id uid,
u.name uname,
u.age uage,
u.address uaddress
from account a
left join user u
on a.uid =u.id;
</select>
</mapper>
方案二:按查詢嵌套
<select id="findAllAccount" resultMap="AccountUserMap">
select * from account
</select>
<select id="findUserById" resultType="User">
select * from user where id =#{uid}
</select>
<resultMap id="AccountUserMap" type="Account">
<!-- 數據庫的字段名和pojo對象中的屬性名一致,可以不用映射,但是要再次基於uid執行嵌套查詢,則需將uid表明.將u查詢結果封裝-->
<id property="uid" column="uid"/>
<association property="user" javaType="User" select="findUserById" column="uid"/>
</resultMap>
方案一二測試如下
//查詢多(一)個賬戶對應一個用戶
@Test
public void test2() {
AccountMapper mapper = DBUtil.getMapper(AccountMapper.class);
List<Account> allAccount = mapper.findAllAccount();
for (Account account : allAccount) {
System.out.println(account);
}
}
測試結果如下:
Account(id=1, uid=null, money=1000.0, user=User(id=1, name=張三, age=18, address=河北, accounts=null))
Account(id=2, uid=null, money=3000.0, user=User(id=1, name=張三, age=18, address=河北, accounts=null))
Account(id=3, uid=null, money=5000.0, user=User(id=3, name=王五, age=30, address=天津, accounts=null))
5 總結
一對多查詢時使用collection
多對一查詢時使用association