多表映射
在多表映射中,我们需要将自己置于当前研究的类的角度,将其视为一个实体对象,以便理解与其他类或对象之间的关系。举例来说,在学生与班级之间的关系中,若我们以学生的角度看待,作为一个学生,我们只需对应一个班级。因此,在学生类中,我们只需要包含一个指向班级的引用,用以存储该学生所属的班级信息。而若以班级的视角来看,作为一个班级其中包含多名学生,因此在班级类中应该有一个学生对象的集合,用以存储该班级所包含的所有学生。
对于多对多关系,我们需要明确这种关系实质上源自一对多和多对一的关系,无论从哪个视角观察,其中总有一方是多的。在这种情况下,我们需要在两个相关类中都添加对方类的列表,以便描述不同视角下的多对多关系。这样的设计能够更清晰地反映实体间的复杂关系,确保数据的完整性和准确性。
实体类设计
- 在对一关系下,类中只要包含单个对方对象类型属性即可
- 在对多关系下,类中只要包含对方类型集合属性即可
- 只有真实发生多表查询时,才需要设计和修改实体类,否则不提前设计和修改实体类
- 无论多少张表联查,实体类设计都是两两考虑
- 在查询映射的时候,只需要关注本次查询相关的属性
-- 数据库
CREATE TABLE `t_customer` (`customer_id` INT NOT NULL AUTO_INCREMENT, `customer_name` CHAR(100), PRIMARY KEY (`customer_id`) );
CREATE TABLE `t_order` ( `order_id` INT NOT NULL AUTO_INCREMENT, `order_name` CHAR(100), `customer_id` INT, PRIMARY KEY (`order_id`) );
INSERT INTO `t_customer` (`customer_name`) VALUES ('c01');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o3', '1');
@Data
public class Customer {
private Integer customerId;
private String customerName;
private List<Order> orderList;
}
@Data
public class Order {
private Integer orderId;
private String orderName;
private Customer customer;
}
对一映射
public interface OrderMapper {
Order selectOrderWithCustomer(Integer orderId);
}
<resultMap id="selectOrderWithCustomerResultMap" type="order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<association property="customer" javaType="customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
</association>
</resultMap>
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">
SELECT order_id,order_name,c.customer_id,customer_name
FROM t_order o
LEFT JOIN t_customer c
ON o.customer_id=c.customer_id
WHERE o.order_id=#{orderId}
</select>
<mappers>
<mapper resource="mappers/OrderMapper.xml"/>
</mappers>
@Slf4j
public class MyBatisTest {
private SqlSession session;
@BeforeEach
public void init() throws IOException {
session = new SqlSessionFactoryBuilder()
.build(
Resources.getResourceAsStream("mybatis-config.xml"))
.openSession();
}
@Test
public void testRelationshipToOne() {
OrderMapper orderMapper = session.getMapper(OrderMapper.class);
Order order = orderMapper.selectOrderWithCustomer(2);
log.info("order = " + order);
}
@AfterEach
public void clear() {
session.commit();
session.close();
}
}
对多映射
public interface CustomerMapper {
Customer selectCustomerWithOrderList(Integer customerId);
}
<resultMap id="selectCustomerWithOrderListResultMap"
type="customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<collection property="orderList" ofType="order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
</collection>
</resultMap>
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
FROM t_customer c
LEFT JOIN t_order o
ON c.customer_id=o.customer_id
WHERE c.customer_id=#{customerId}
</select>
<mappers>
<mapper resource="mappers/OrderMapper.xml"/>
<mapper resource="mappers/CustomerMapper.xml"/>
</mappers>
@Test
public void testRelationshipToMulti() {
CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
Customer customer = customerMapper.selectCustomerWithOrderList(1);
log.info("customer.getCustomerId() = " + customer.getCustomerId());
log.info("customer.getCustomerName() = " + customer.getCustomerName());
List<Order> orderList = customer.getOrderList();
for (Order order : orderList) {
log.info("order = " + order);
}
}