Mybatis的多表查询
一、一对一的查询(<assocation>)
1、创建User类(用户类):
public class User implements Serializable {
private static final long serialVersionUID = 6716332190979093860L;
private Integer Id;
private String username;
private String sex;
private String password;
private Date birthday;
private Department department;
//get/set方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((department == null) ? 0 : department.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((password == null) ? 0 : password.hashCode());
result = prime * result + ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (department == null) {
if (other.department != null)
return false;
} else if (!department.equals(other.department))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
2、创建Department类(部门类)
public class Department {
private Integer dep_id;
private String dep_name;
private String manager;
//get/set方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Department other = (Department) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
分析
-
我们知道一个用户只能属于一个部门,因此这里在User类中只是使用了Department对象,而不是个集合
-
那么我们想要查询所有的用户信息和其所在的部门信息,此时的sql语句为:select * from db_user u left join db_department d on u.dep_id=d.dep_id;。但是我们在mybaits中如果使用这条语句查询,那么返回的结果类型是什么呢?如果是User类型的,那么查询结果返回的还有Department类型的数据,那么肯定会对应不上的。
-
我们可以使用resultMap解决对应问题
实现
-
使用resultMap解决查询结果的对应问题
-
这里一定要在resultMap将每一个字段和查询结果返回的字段对应上,否则此时的结果就为null
<!-- 定义resultMap -->
<resultMap type="User" id="userDepartment">
<!-- 配置id的对应 -->
<id property="Id" column="id" javaType="java.lang.Integer"/>
<!-- 配置其他字段的对应关系
column: 查询结果中的列名字,如果没有起别名,那么就是表中的字段名
property: java类中的属性名称
-->
<result property="username" column="name" javaType="java.lang.String"/>
<result property="sex" column="sex" javaType="java.lang.String"/>
<result property="birthday" column="birthday" javaType="java.util.Date"/>
<result property="password" column="password" javaType="java.lang.String"/>
<!-- 配置对1的数据类型,即User类中的Department对象是单一的具体类型
property: 这个是在User类中的字段名称
javaType: 这个是java类的全名,是Department类的全名
-->
<association property="department" javaType="Department">
<id property="dep_id" column="dep_id"/>
<result property="dep_name" column="dep_name"/>
<result property="manager" column="manager"/>
</association>
</resultMap>
<!--
User findUserAndDepartment();
resultMap: 指定上面resultMap的id的值
-->
<select id="findUserAndDepartment" resultMap="userDepartment">
select * from db_user u left join db_department d on u.dep_id=d.dep_id
</select>
注: association字面意思关联,这里只专门做一对一关联; property表示是属性名称; javaType表示该属性是什么类型对象
测试方法
public class MybatisTest {
@Test
public void test() {
SqlSession session = DBTools.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
try {
List<User> list = mapper.findUserAndDepartment();
for(User u:list) {
System.out.println(u);
}
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally {
session.close();
}
}
}
二、一对多的查询(<collection>):一个宿舍可以住多个学生,那么我们通过宿舍查询学生,那么就是一对多查询。
1、创建Student类:
public class Student implements Serializable {
private static final long serialVersionUID = 8673238196042278929L;
private Integer id;
private String name;
private Integer age;
//省略set/get方法
}
2、创建Dormitory类: 其中有一个Set<Student>集合用来存储学生对象
public class Dormitory implements Serializable{
private static final long serialVersionUID = 1359749532219773083L;
private Integer id;
private String number; //编号
private Set<Student> students; //学生集合,一个宿舍可以住多个学生
//省略set/get方法
}
3、创建表
create table student(id int primary key auto_increment,name varchar(10) not null unique,age int,dormitory_id int);
create table dormitory(id int primary key auto_increment,number varchar(20) not null unique);
4、创建DormitoryMapper.java(接口)
public interface DormitoryMapper {
//查询所有的宿舍信息
List<Dormitory> findDormitories();
//根据id查询宿舍信息
Dormitory findDormitory(Integer id);
}
5、创建DormitoryMapper.xml
<!-- MyBatis的接口映射文件,根节点是mapper -->
<!-- 接口映射文件是与Java接口文件(interface)相对应的 -->
<!-- 根节点的namespace属性用于指定Java接口文件 -->
<mapper namespace="cn.tedu.spring.mapper.DormitoryMapper">
<!-- 定义resultMap-->
<resultMap type="cn.tedu.spring.entity.Dormitory" id="DormitoryStudentRs">
<id column="id" property="id"/>
<result column="number" property="number"/>
<!-- 因为Dormitoy中的Student使用set集合存储的,因此这里使用collection标签
property : Java类中的集合对象
ofType: 集合对象的泛型类型
-->
<collection property="students" ofType="cn.tedu.spring.entity.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</collection>
</resultMap>
<!-- List<Dormitory> findDormitories();查询所有的宿舍信息
resultMap: 指定前面定义的resultMap
-->
<select id="findDormitories" resultMap="DormitoryStudentRs">
select * from student s left join dormitory d on s.dormitory_id=d.id
</select>
<!--
Dormitory findDormitory(Integer id);
-->
<select id="findDormitory" resultType="cn.tedu.spring.entity.Dormitory">
select * from dormitory where id=#{id}
</select>
</mapper>
注: collection字面意思是集合,这里专门做一对多关联 ,property表示集合类型属性名称,ofType表示集合中的对象是什么类型
6、在配置文件中添加DormitoryMapper.xml文件
7、测试
@Test
public void testFindDormitory() {
DormitoryMapper dormitoryMapper=ac.getBean("dormitoryMapper",DormitoryMapper.class);
//执行查询方法
List<Dormitory> dormitories=dormitoryMapper.findDormitories();
for (Dormitory dormitory : dormitories) {
System.out.println(dormitory);
}
ac.close();
}
三、多对多查询:
1、类之间的关系:
2、对应的表:
3、思路
(1)将用户信息映射到User中;
(2) 在User类中添加订单列表属性List<Orders>ordersList,将用户创建的订单映射到ordersList中;
(3)在Orders中添加订单明细列表属性List<OrderDetail>orderDetails,将订单的明细映射到orderDetails中;
(4)在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items中。
4、定义持久化类:
User.java
//客户类
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private int id; //编号
private String username; //用户名
private String gender; //性别
private Date birthday; //生日
private String address; //地址
private List<Orders> OrdersList;//订单列表
}
Items.java
//商品类
public class Items implements Serializable{
private static final long serialVersionUID = 1L;
private int id; //商品编号
private String name;//商品名称
private double price;//商品价格
private String detail;//商品描述
private String pic;//商品图片
private Date createTime;//生产时间
}
Orders.java
//订单类
public class Orders implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;//流水号
private Integer userId;//用户编号
private String number;//订单编号
private Date createTime;//创建时间
private String note;//备注
private List<Orderdetail> orderdetails;//订单明细
}
Orderdetail.java
//订单明细
public class Orderdetail implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private Integer ordersId;//订单编号
private Integer itemsId;//商品编号
private Double itemsNum;//商品数量
private Items items;//明细对应的商品信息
}
5、创建代理 即mapper.java
public interface OrdersMapperUser {
//查询用户购买的商品信息
public List<User> findUserAndItemsResultMap() throws Exception;
}
6、创建映射文件OrdersMapperCustom.xml
<mapper namespace="com.mybatis.mapper.OrdersMapperUser">
<!--查询用户购买的商品-->
<resultMap id="UserAndItemsResultMap" type="User">
<!-- 用户信息映射 -->
<id property="id" column="user_id" javaType="java.lang.Integer"/>
<result property="username" column="user_name" javaType="java.lang.String"/>
<result property="gender" column="user_gender" javaType="java.lang.String"/>
<result property="birthday" column="user_birthday" javaType="java.util.Date"/>
<result property="address" column="user_address" javaType="java.lang.String"/>
<!--订单信息-->
<!--一个用户可以对应多个订单,故使用collection映射-->
<collection property="OrdersList" ofType="Orders" fetchType="lazy">
<id property="id" column="order_id" javaType="java.lang.Integer" />
<result property="userId" column="user_id" javaType="java.lang.Integer"/>
<result property="number" column="order_number" javaType="java.lang.String"/>
<result property="createTime" column="order_createTime" javaType="java.util.Date"/>
<result property="note" column="order_note" javaType="java.lang.String"/>
<!--订单明细-->
<!--一个订单包括多个明细,故使用collection-->
<collection property="orderdetails" ofType="Orderdetail" fetchType="lazy">
<id property="id" column="orderdetil_id" javaType="java.lang.Integer"/>
<result property="itemsId" column="item_id" javaType="java.lang.Integer"/>
<result property="ordersId" column="order_id" javaType="java.lang.Integer"/>
<result property="itemsNum" column="item_num" javaType="java.lang.Double"/>
<!--商品信息-->
<!--一个订单明细对应一个商品,故使用association -->
<association property="items" javaType="Items">
<id property="id" column="item_id" javaType="java.lang.Integer"/>
<result property="name" column="item_name" javaType="java.lang.String"/>
<result property="price" column="item_price" javaType="java.lang.Double"/>
<result property="detail" column="item_detail" javaType="java.lang.String"/>
<result property="pic" column="item_picture" javaType="java.lang.String"/>
<result property="createTime" column="createTime" javaType="java.util.Date"/>
</association>
</collection>
</collection>
</resultMap>
<select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
SELECT
orders.*,
user.user_name,
user.user_gender,
user.user_address,
orderdetail.orderdetail_id,
orderdetail.item_id,
orderdetail.item_num,
orderdetail.order_id,
items.item_name,
items.item_detail,
items.item_price
FROM
orders,
user,
orderdetail,
items
WHERE orders.user_id=user.user_id AND orders.order_id = orderdetail.order_id AND orderdetail.item_id=items.item_id
</select>
</mapper>
7、测试