文章目录
- 数据库设计
- MyBatis 配置
- MyBatis 映射文件
- Mapper 接口
- 总结
数据库设计
建表 SQL
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL
);CREATE TABLE `order` (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT NOT NULL,order_no VARCHAR(50) NOT NULL,FOREIGN KEY (user_id) REFERENCES user(id)
);CREATE TABLE role (id INT PRIMARY KEY AUTO_INCREMENT,role_name VARCHAR(50) NOT NULL
);CREATE TABLE user_role (user_id INT NOT NULL,role_id INT NOT NULL,PRIMARY KEY (user_id, role_id),FOREIGN KEY (user_id) REFERENCES user(id),FOREIGN KEY (role_id) REFERENCES role(id)
);
插入以下数据:
INSERT INTO user (name) VALUES ('Alice'), ('Bob');
INSERT INTO `order` (user_id, order_no) VALUES (1, 'ORD001'), (1, 'ORD002'), (2, 'ORD003');
INSERT INTO role (role_name) VALUES ('Admin'), ('User');
INSERT INTO user_role (user_id, role_id) VALUES (1, 1), (1, 2), (2, 2);
MyBatis 配置
我们使用 MySQL 数据库,MyBatis 的核心配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>
定义 Java 实体类,映射数据库表:
@Data
public class User {private Integer id;private String name;private Order order; // 一对一:用户关联一个订单private List<Order> orders; // 一对多:用户关联多个订单private List<Role> roles; // 多对多:用户关联多个角色
}@Data
public class Order {private Integer id;private Integer userId;private String orderNo;
}@Data
public class Role {private Integer id;private String roleName;
}
MyBatis 映射文件
在 UserMapper.xml 中定义关联查询,展示一对一、一对多和多对多的实现。
<?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.example.mapper.UserMapper"><!-- 一对一 --><resultMap id="UserWithOrderMap" type="com.example.entity.User"><id property="id" column="user_id"/><result property="name" column="user_name"/><association property="order" javaType="com.example.entity.Order"><id property="id" column="order_id"/><result property="userId" column="user_id"/><result property="orderNo" column="order_no"/></association></resultMap><select id="selectUserWithOrder" resultMap="UserWithOrderMap">SELECT *FROM user uLEFT JOIN `order` o ON u.id = o.user_idWHERE u.id = #{id}LIMIT 1</select><!-- 一对多 --><resultMap id="UserWithOrdersMap" type="com.example.entity.User"><id property="id" column="user_id"/><result property="name" column="user_name"/><collection property="orders" ofType="com.example.entity.Order"><id property="id" column="order_id"/><result property="userId" column="user_id"/><result property="orderNo" column="order_no"/></collection></resultMap><select id="selectUserWithOrders" resultMap="UserWithOrdersMap">SELECT *FROM user uLEFT JOIN `order` o ON u.id = o.user_idWHERE u.id = #{id}</select><!-- 多对多 --><resultMap id="UserWithRolesMap" type="com.example.entity.User"><id property="id" column="user_id"/><result property="name" column="user_name"/><collection property="roles" ofType="com.example.entity.Role"><id property="id" column="role_id"/><result property="roleName" column="role_name"/></collection></resultMap><select id="selectUserWithRoles" resultMap="UserWithRolesMap">SELECT *FROM user uLEFT JOIN user_role ur ON u.id = ur.user_idLEFT JOIN role r ON ur.role_id = r.idWHERE u.id = #{id}</select>
</mapper>
Mapper 接口
定义对应的 Mapper 接口:
public interface UserMapper {User selectUserWithOrder(Integer id); // 一对一User selectUserWithOrders(Integer id); // 一对多User selectUserWithRoles(Integer id); // 多对多
}
以下是测试代码,验证查询结果:
public class MyBatisTest {public static void main(String[] args) throws Exception {SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml"));try (SqlSession session = factory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);// 测试一对一User userWithOrder = mapper.selectUserWithOrder(1);System.out.println(userWithOrder.getName());// 测试一对多User userWithOrders = mapper.selectUserWithOrders(1);System.out.println(userWithOrders.getName());userWithOrders.getOrders().forEach(order -> System.out.println(" - " + order.getOrderNo()));// 测试多对多User userWithRoles = mapper.selectUserWithRoles(1);System.out.println(userWithRoles.getName());userWithRoles.getRoles().forEach(role -> System.out.println(" - " + role.getRoleName()));}}
}
总结
一对一:通过 association 标签,查询用户及其关联的一个订单。
一对多:通过 collection 标签,查询用户及其所有订单,MyBatis 自动将多行订单数据映射到 List。
多对多:通过 collection 标签,查询用户及其所有角色,借助中间表 user_role 实现关联。