有2個實體:用戶、訂單,一個用戶可以擁有多個訂單,同時這多個訂單屬於一個用戶,即一對多。
user_tb:
order_tb:
在“多”的一方(order)添加“一”的一方(user)的主鍵(user_id)作為外鍵。
使用嵌套結果
(1)給2個實體都編寫pojo類,需要在“一”的一方寫個List來關聯“多”的一方
package com.chy.pojo; public class Order { private Integer no; private Integer userId; private Integer goodsId; private Integer goodsAmount; public Integer getNo() { return no; } public void setNo(Integer no) { this.no = no; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getGoodsId() { return goodsId; } public void setGoodsId(Integer goodsId) { this.goodsId = goodsId; } public Integer getGoodsAmount() { return goodsAmount; } public void setGoodsAmount(Integer goodsAmount) { this.goodsAmount = goodsAmount; } @Override public String toString() { return "Order{" + "no=" + no + ", userId=" + userId + ", goodsId=" + goodsId + ", goodsAmount=" + goodsAmount + '}'; } }
package com.chy.pojo; import java.util.List; public class User { private Integer id; private String username; private String password; private String tel; private String address; private List<Order> orderList; 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public List<Order> getOrderList() { return orderList; } public void setOrderList(List<Order> orderList) { this.orderList = orderList; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", tel='" + tel + '\'' + ", address='" + address + '\'' + ", orderList=" + orderList + '}'; } }
toString()只是為了方便測試、調試,后期可以去掉。
(2)給“一”的一方寫Mapper接口、xml映射文件
package com.chy.mapper; import com.chy.pojo.User; public interface UserMapper { public User queryUserById(Integer id); }
<?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.chy.mapper.UserMapper"> <select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder"> SELECT user_tb.*,order_tb.* FROM user_tb,order_tb WHERE user_tb.id=#{id} AND order_tb.user_id=user_tb.id </select> <resultMap id="userResultWithOrder" type="user"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="tel" column="tel"/> <result property="address" column="address"/> <collection property="orderList" ofType="order"> <id property="no" column="no"/>
<result property="userId" column="user_id" /> <result property="goodsId" column="goods_id" /> <result property="goodsAmount" column="goods_amount" /> </collection> </resultMap> </mapper>
因為關聯的是集合(List),所以用<collection>。
- property指定表示關聯對象的成員變量名
- ofType指定返回的數據類型,注意不是list。
- 子元素<id>、<result>配置關聯對象的映射。
所謂關聯查詢,是查詢結果中同時包含雙方(2張表)的多個字段,
如果只查詢一張表的字段,比如說只查詢某個用戶的訂單,不查詢此用戶本身的信息,直接根據外鍵user_id查order_tb表,不需要查user_tb,不必使用關聯查詢,寫個OrderMapper接口、OrderMapper.xml就ok。
(3)使用
package com.chy.utils; 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 java.io.IOException; import java.io.InputStream; public class MyBatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
package com.chy.test; import com.chy.mapper.UserMapper; import com.chy.pojo.User; import com.chy.utils.MyBatisUtils; import org.apache.ibatis.session.*; public class Test { public static void main(String[] args) { SqlSession sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); sqlSession.close(); } }
使用嵌套查詢
與嵌套結果大體相同,不同的只有第二步:
(二)給雙方都編寫Mapper接口、映射文件
package com.chy.mapper; import com.chy.pojo.Order; public interface OrderMapper { //根據orderId查詢訂單信息 public Order queryOrderByUserId(Integer userId); }
<?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.chy.mapper.OrderMapper"> <select id="queryOrderByUserId" parameterType="integer" resultMap="orderMap"> SELECT * FROM order_tb WHERE user_id=#{id} </select> <resultMap id="orderMap" type="order"> <id property="no" column="no"/> <result property="userId" column="user_id"/> <result property="goodsId" column="goods_id"/> <result property="goodsAmount" column="goods_amount"/> </resultMap> </mapper>
package com.chy.mapper; import com.chy.pojo.User; public interface UserMapper { public User queryUserById(Integer id); }
<?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.chy.mapper.UserMapper"> <select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder"> SELECT * FROM user_tb WHERE id=#{id} </select> <resultMap id="userResultWithOrder" type="user"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="tel" column="tel"/> <result property="address" column="address"/> <collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/> </resultMap> </mapper>
column指定向子查詢傳遞的參數是當前表的哪一列。
<resultMap>中的映射問題
我在<resultMap>中使用了子元素<id>、<result>配置了所有的表字段——pojo類屬性之間的映射,
其實只要表字段、pojo類屬性的名稱一致,就不必配置,比如
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="tel" column="tel"/>
<result property="address" column="address"/>
<collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/>
</resultMap>
紅色部分完全可以省略,因為默認的映射就是pojo類屬性、表字段名稱一致。
如果部分不一致,只需配置不一致的部分,比如只有用戶id的不一致:
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="user_id"/>
<collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/>
</resultMap>