Mybatis的多表操作

it2025-03-19  19

1.Mybatis多表查询

1.1 一对一查询

1.1.1 一对一查询的模型MapperScannerConfigurer

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

1.1.2一对一查询的语句

对应的sql语句:select * from orders o,user u where o.uid=u.id;

查询的结果如下:

 

1.1.3 创建Order和User实体

public class Order { private int id; private Date ordertime; private double total; //代表当前订单从属于哪一个客户 private User user; } public class User { private int id; private String username; private String password; private Date birthday; }

1.1.4 创建OrderMapper接口

public interface OrderMapper { List<Order> findAll(); }

1.1.5 配置OrderMapper.xml

主键ID比较的特殊,因此使用id column

其他的用result

<?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.itheima.mapper.OrderMapper"> <resultMap id="orderMap" type="com.itheima.domain.Order"> <!--手动指定字段与实体属性的映射关系 column: 数据表的字段名称 property:实体的属性名称 --> <id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> <result column="uid" property="user.id"></result> <result column="username" property="user.username"></result> <result column="password" property="user.password"></result> <result column="birthday" property="user.birthday"></result> </resultMap> <select id="findAll" resultMap="orderMap"> SELECT *,o.id oid FROM orders o,USER u WHERE o.uid=u.id </select> </mapper>

 换种封装方式,将user单独配置了

<id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> <!--<result column="uid" property="user.id"></result> <result column="username" property="user.username"></result> <result column="password" property="user.password"></result> <result column="birthday" property="user.birthday"></result>--> <!-- property: 当前实体(order)中的属性名称(private User user) javaType: 当前实体(order)中的属性的类型(User) --> <association property="user" javaType="user"> <id column="uid" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="birthday" property="birthday"></result> </association>

 

1.1.6 测试结果

@Test public void test1() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); OrderMapper mapper = sqlSession.getMapper(OrderMapper.class); List<Order> orderList = mapper.findAll(); for (Order order : orderList) { System.out.println(order); } sqlSession.close(); }

 

1.2 一对多查询

1.2.1 一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

1.2.2 一对多查询的语句

       SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid

查询的结果如下:

1.2.3 修改User实体

public class Order { private int id; private Date ordertime; private double total; //代表当前订单从属于哪一个客户 private User user; } public class User { private int id; private String username; private String password; private Date birthday; //代表当前用户具备哪些订单 private List<Order> orderList; }

1.2.4 创建UserMapper接口

public interface UserMapper { List<User> findAll(); }

1.2.5 配置UserMapper.xml

<mapper namespace="com.itheima.mapper.UserMapper"> <resultMap id="userMap" type="com.itheima.domain.User"> <id column="uid" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="birthday" property="birthday"></result> <!--配置集合信息 property:集合名称 ofType:当前集合中的数据类型 --> <collection property="orderList" ofType="com.itheima.domain.Order"> <!--封装order的数据--> <id column="oid" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> </collection> </resultMap> <select id="findAll" resultMap="userMap"> SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid </select> </mapper>

1.2.6 测试结果

@Test public void test2() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.findAll(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }

1.3 多对多查询

1.3.1 多对多查询的模型

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用

多对多查询的需求:查询用户同时查询出该用户的所有角色

核心就是user_rolse的两个外键

1.3.2 多对多查询的语句

对应的sql语句:   SELECT * FROM USER u,sys_user_role ur,sys_role r WHERE u.id=ur.userId AND ur.roleId=r.id

查询的结果如下:

1.3.3 创建Role实体,修改User实体

 

package com.itheima.domain; public class Role { private int id; private String roleName; private String roleDesc; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } @Override public String toString() { return "Role{" + "id=" + id + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; } } public class User { private int id; private String username; private String password; private Date birthday; //代表当前用户具备哪些订单 private List<Order> orderList; //代表当前用户具备哪些角色 private List<Role> roleList; } public class Role { private int id; private String rolename; }

1.3.4 添加UserMapper接口方法

public List<User> findUserAndRoleAll();

1.3.5 配置UserMapper.xml

<!--自定义别名--> <typeAliases> <typeAlias type="com.itheima.domain.User" alias="user"></typeAlias> <typeAlias type="com.itheima.domain.Order" alias="order"></typeAlias> <typeAlias type="com.itheima.domain.Role" alias="role"></typeAlias> </typeAliases> <resultMap id="userRoleMap" type="user"> <!--user的信息--> <id column="userId" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="birthday" property="birthday"></result> <!--user内部的roleList信息--> <collection property="roleList" ofType="role"> <id column="roleId" property="id"></id> <result column="roleName" property="roleName"></result> <result column="roleDesc" property="roleDesc"></result> </collection> </resultMap> <select id="findUserAndRoleAll" resultMap="userRoleMap"> SELECT * FROM USER u,sys_user_role ur,sys_role r WHERE u.id=ur.userId AND ur.roleId=r.id </select>

1.3.6 测试结果

@Test public void test3() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userAndRoleAll = mapper.findUserAndRoleAll(); for (User user : userAndRoleAll) { System.out.println(user); } sqlSession.close(); }

1.4 知识小结

MyBatis多表配置方式:

一对一配置:使用<resultMap>做配置

一对多配置:使用<resultMap>+<collection>做配置

多对多配置:使用<resultMap>+<collection>做配置

 

2.Mybatis的注解开发

2.1 MyBatis的常用注解

这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper

映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。

@Insert:实现新增

@Update:实现更新

@Delete:实现删除

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result 一起使用,封装多个结果集

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

2.2 MyBatis的增删改查

我们完成简单的user表的增删改查的操作

public class MyBatisTest { private UserMapper mapper; @Before public void before() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); mapper = sqlSession.getMapper(UserMapper.class); } @Test public void testSave(){ User user = new User(); user.setUsername("tom"); user.setPassword("abc"); mapper.save(user); } @Test public void testUpdate(){ User user = new User(); user.setId(18); user.setUsername("lucy"); user.setPassword("123"); mapper.update(user); } @Test public void testDelete(){ mapper.delete(18); } @Test public void testFindById(){ User user = mapper.findById(2); System.out.println(user); } @Test public void testFindAll(){ List<User> all = mapper.findAll(); for (User user : all) { System.out.println(user); } } }

 配置UserMapper的接口

package com.itheima.mapper; import com.itheima.domain.User; import org.apache.ibatis.annotations.*; import java.util.List; public interface UserMapper { @Insert("insert into user values(#{id},#{username},#{password},#{birthday})") public void save(User user); @Update("update user set username=#{username},password=#{password} where id=#{id}") public void update(User user); @Delete("delete from user where id=#{id}") public void delete(int id); @Select("select * from user where id=#{id}") public User findById(int id); @Select("select * from user") public List<User> findAll(); @Select("select * from user") @Results({ @Result(id=true ,column = "id",property = "id"), @Result(column = "username",property = "username"), @Result(column = "password",property = "password"), @Result( property = "orderList", column = "id", javaType = List.class, many = @Many(select = "com.itheima.mapper.OrderMapper.findByUid") ) }) public List<User> findUserAndOrderAll(); @Select("SELECT * FROM USER") @Results({ @Result(id = true,column = "id",property = "id"), @Result(column = "username",property = "username"), @Result(column = "password",property = "password"), @Result( property = "roleList", column = "id", javaType = List.class, many = @Many(select = "com.itheima.mapper.RoleMapper.findByUid") ) }) public List<User> findUserAndRoleAll(); }

修改MyBatis的核心配置文件,我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可,或者指定扫描包含映射关系的接口所在的包也可以

<!--加载映射关系--> <mappers> <!--指定接口所在的包--> <package name="com.itheima.mapper"></package> </mappers>

2.3 MyBatis的注解实现复杂映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置

 

2.4 一对一查询

2.4.1 一对一查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

 

2.4.2 一对一查询的语句

对应的sql语句:

select * from orders; select * from user where id=查询出订单的uid;

 

2.4.3 创建Order和User实体

public class Order { private int id; private Date ordertime; private double total; //代表当前订单从属于哪一个客户 private User user; } public class User { private int id; private String username; private String password; private Date birthday; }

2.4.4 创建OrderMapper接口

public interface OrderMapper { List<Order> findAll(); }

 

2.4.5 使用注解配置Mapper

@Select("select *,o.id oid from orders o,user u where o.uid=u.id") @Results({ @Result(column = "oid",property = "id"), @Result(column = "ordertime",property = "ordertime"), @Result(column = "total",property = "total"), @Result(column = "uid",property = "user.id"), @Result(column = "username",property = "user.username"), @Result(column = "password",property = "user.password") }) public List<Order> findAll();

  

对应的sql语句:  

select * from orders; select * from user where id=查询出订单的uid; @Select("select * from orders") @Results({ @Result(column = "id",property = "id"), @Result(column = "ordertime",property = "ordertime"), @Result(column = "total",property = "total"), @Result( property = "user", //要封装的属性名称 column = "uid", //根据那个字段去查询user表的数据 javaType = User.class, //要封装的实体类型 //select属性 代表查询那个接口的方法获得数据 one = @One(select = "com.itheima.mapper.UserMapper.findById") ) }) public List<Order> findAll(); public interface UserMapper { @Select("select * from user where id=#{id}") User findById(int id); }

 通过查询结果中的uid再进行查询,执行查询语句

2.4.6 测试结果

package com.itheima.test; import com.itheima.domain.Order; import com.itheima.domain.User; import com.itheima.mapper.OrderMapper; import com.itheima.mapper.UserMapper; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MyBatisTest2 { private OrderMapper mapper; @Before public void before() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); mapper = sqlSession.getMapper(OrderMapper.class); } @Test public void testSave(){ List<Order> all = mapper.findAll(); for (Order order : all) { System.out.println(order); } } }

 

2.5 一对多查询

2.5.1 一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

select * from user; select * from orders where uid=查询出用户的id;

2.5.3 修改User实体

public class Order { private int id; private Date ordertime; private double total; //代表当前订单从属于哪一个客户 private User user; } public class User { private int id; private String username; private String password; private Date birthday; //代表当前用户具备哪些订单 private List<Order> orderList; }

2.5.4 创建UserMapper接口

public List<User> findUserAndOrderAll();

2.5.5 使用注解配置Mapper

public interface UserMapper { @Select("select * from user") @Results({ @Result(id=true ,column = "id",property = "id"),//主键 @Result(column = "username",property = "username"), @Result(column = "password",property = "password"), @Result( property = "orderList", column = "id", javaType = List.class, many = @Many(select = "com.itheima.mapper.OrderMapper.findByUid") ) }) public List<User> findUserAndOrderAll(); } public interface OrderMapper { @Select("select * from orders where uid=#{uid}") List<Order> findByUid(int uid); }

2.5.6 测试结果

public class MyBatisTest3 { private UserMapper mapper; @Before public void before() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); mapper = sqlSession.getMapper(UserMapper.class); } @Test public void testSave(){ List<User> userAndOrderAll = mapper.findUserAndOrderAll(); for (User user : userAndOrderAll) { System.out.println(user); } } }

 

 

2.6 多对多查询

2.6.1 多对多查询的模型

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用

多对多查询的需求:查询用户同时查询出该用户的所有角色

2.6.2 多对多查询的语句

2.6.3 创建Role实体,修改User实体

public class User { private int id; private String username; private String password; private Date birthday; //代表当前用户具备哪些角色 private List<Role> roleList; } public class Role { private int id; private String rolename; }

2.6.4 添加UserMapper接口方法

public List<User> findUserAndRoleAll();

2.6.5 使用注解配置Mapper

@Select("SELECT * FROM USER") @Results({ @Result(id = true,column = "id",property = "id"), @Result(column = "username",property = "username"), @Result(column = "password",property = "password"), @Result( property = "roleList", column = "id", javaType = List.class, many = @Many(select = "com.itheima.mapper.RoleMapper.findByUid") ) }) public List<User> findUserAndRoleAll(); public interface RoleMapper { @Select("SELECT * FROM sys_user_role ur,sys_role r WHERE ur.roleId=r.id AND ur.userId=#{uid}") public List<Role> findByUid(int uid); }

2.6.6 测试结果

public class MyBatisTest4 { private UserMapper mapper; @Before public void before() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); mapper = sqlSession.getMapper(UserMapper.class); } @Test public void testSave(){ List<User> userAndRoleAll = mapper.findUserAndRoleAll(); for (User user : userAndRoleAll) { System.out.println(user); } } }

 

最新回复(0)