MyBatis的关联映射(全)五
MyBatis的关联映射(全)
学习要点
一对一
一对多
多对一
多对多
目录结构
一对一
一对一推荐使用唯一主外键关联,一对一一般会吧外键设置为唯一约束,下面举例子为一用户对应一个人身份账号。
1.创建身份证表和用户表并插入数据
CREATE TABLE `m_card` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '身份证id',
`cardname` varchar(16) DEFAULT NULL COMMENT '身份证的名称',
`cardadd` varchar(255) DEFAULT NULL COMMENT '身份证的地址',
`cardnum` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(66) DEFAULT NULL,
`password` varchar(66) DEFAULT NULL,
`deptid` int(11) DEFAULT NULL,
`cardid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`m_card` (`id`, `cardname`, `cardadd`, `cardnum`) VALUES ('1', '小星星', '中国', '411481199606104867');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('3', 'root384722669', 'password1942141865', '1', NULL);
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('4', 'root487129123', 'password-902996385', NULL, NULL);
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('5', 'root1461712382', 'password-381676017', '1', NULL);
2.创建实体类User
package com.pkk.entity;
import java.io.Serializable;
/**
* @author peikunkun
* @version V1.0
* @Title: MyBatisProject
* @Package com.pkk.entity
* @Description: <>
* @date 2017/12/31 19:31
*/
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String cardid;
private Card card;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public String getCardid() {
return cardid;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
public void setCardid(String cardid) {
this.cardid = cardid;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", cardid='" + cardid + '\'' +
", card=" + card +
'}';
}
}
3.创建实体类Dept
package com.pkk.entity;
import java.io.Serializable;
/**
* Created by peikunkun on 2018/1/25 0025.
*/
public class Card implements Serializable {
private Integer id;
private String cardname;
private String cardadd;
private String cardnum;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCardname() {
return cardname;
}
public void setCardname(String cardname) {
this.cardname = cardname;
}
public String getCardadd() {
return cardadd;
}
public void setCardadd(String cardadd) {
this.cardadd = cardadd;
}
public String getCardnum() {
return cardnum;
}
public void setCardnum(String cardnum) {
this.cardnum = cardnum;
}
@Override
public String toString() {
return "Card{" +
"id=" + id +
", cardname='" + cardname + '\'' +
", cardadd='" + cardadd + '\'' +
", cardnum='" + cardnum + '\'' +
'}';
}
}
4.创建一对一的配置文件(userMapper4.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.pkk.test.mappertest.userMapper4">
<!--一对一的关系-->
<resultMap id="cardAndUser" type="com.pkk.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<association property="card" column="cardid" javaType="com.pkk.entity.Card" select="selectCardById1">
<id property="id" column="id"/>
<result property="cardname" column="cardname"/>
<result property="cardadd" column="cardadd"/>
<result property="cardnum" column="cardnum"/>
</association>
</resultMap>
<!---->
<select id="selectCardById1" resultType="com.pkk.entity.Card" parameterType="int" useCache="false" timeout="15">
SELECT m.* from m_card m where m.id=#{id}
</select>
<select id="selectUserById1" resultMap="cardAndUser" parameterType="int">
SELECT * FROM USER where id=#{id}
</select>
</mapper>
5.MyBatis的总配置文件(mybatis-config.xml)
<?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>
<!--指定MyBatis所用的日志具体实现-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!--起别名,别名的作用就是用简单明代替全限定类名-->
<typeAliases>
<!--
通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
<package name="com.pkk.entity"/>
-->
<typeAlias alias="user" type="com.pkk.entity.User"/>
</typeAliases>
<!--环境配置,即连接的数据库-->
<environments default="mysql">
<environment id="mysql">
<!--使用jdbc的事务提交与回滚设置-->
<transactionManager type="JDBC"/>
<!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="username" value="***"/>
<property name="password" value="***"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
</dataSource>
</environment>
</environments>
<!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
<mappers>
<!--多表关联查询(全)-->
<mapper resource="com.pkk.test/mappertest/userMapper4.xml"></mapper>
</mappers>
</configuration>
6.测试方法
package com.pkk.test.association;
import com.alibaba.fastjson.JSONObject;
import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.Map;
/**
* Created by peikunkun on 2018/1/25 0025.
*/
public class AssociationTest1 {
private SqlSession session = null;
@Before
public void before() {
session = TestUtil.getSqlSession();
}
@Test
public void AssociationTest1_12() {
System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
System.out.println("此方法测试描述:【一对一的映射关联】");
List<User> users = session.selectList("com.pkk.test.mappertest.userMapper4.selectUserById1", 1);
System.out.println(users);
}
@After
public void end() {
TestUtil.commitAndCloseSession(session);
}
}
7.测试工具类
package com.pkk.test;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
/**
* Created by peikunkun on 2018/1/21 0021.
*/
public class TestUtil {
/**
* 获取连接
*
* @return
*/
public static SqlSession getSqlSession() {
/*获取当前mybatis配置文件*/
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
/*创建sqlSessionFactory对象*/
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/*创建SQLSession对象操作持久层对象*/
SqlSession session = sqlSessionFactory.openSession();
return session;
}
/**
* 关闭连接和进行提交
*
* @return
*/
public static void commitAndCloseSession(SqlSession session) {
if (session != null) {
session.commit();
session.close();
}
}
}
8.代码讲解
就这样当我们查询User的时候也会把Card查出来
一对多
数据库中维护一对多的关系一般是主外键关联,外键应该在多的一方,也就是多的一方进行维护,下面例子是一个部门对应多个用户。
1.数据库表
CREATE TABLE `dept` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门id',
`deptname` varchar(50) DEFAULT NULL COMMENT '部门名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL COMMENT '用户名',
`password` varchar(32) DEFAULT NULL COMMENT '用户密码',
`deptid` int(11) DEFAULT NULL COMMENT '部门id',
`cardid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`dept` (`id`, `deptname`) VALUES ('1', '昆仔学习部');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('3', 'root384722669', 'password1942141865', '1', NULL);
2.实体类User
package com.pkk.entity;
import java.io.Serializable;
/**
* @author peikunkun
* @version V1.0
* @Title: MyBatisProject
* @Package com.pkk.entity
* @Description: <>
* @date 2017/12/31 19:31
*/
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String cardid;
private Dept dept;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public String getCardid() {
return cardid;
}
public void setCardid(String cardid) {
this.cardid = cardid;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", cardid='" + cardid + '\'' +
", dept=" + dept +
'}';
}
}
3.实体类Dept
package com.pkk.entity;
import java.io.Serializable;
import java.util.List;
/**
* Created by peikunkun on 2018/1/24 0024.
* 《部门表》
*/
public class Dept implements Serializable {
private Integer id;
private String deptname;
/*因为一个部门对应多个员工,所以用集合来接收多个用户*/
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", deptname='" + deptname + '\'' +
", users=" + users +
'}';
}
}
4.一对多的配置文件(userMapper5.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.pkk.test.mappertest.userMapper4">
<!--一对多-->
<resultMap id="deptAndUser" type="com.pkk.entity.Dept">
<id property="id" column="id"/>
<result property="deptname" column="deptname"/>
<collection property="users" column="id" ofType="com.pkk.entity.User" javaType="ArrayList"
select="selectUserById2" fetchType="lazy">
<!--数据库字段与实体字段一致不在书写-->
</collection>
</resultMap>
<!--一对多-->
<select id="selectDeptById1" resultMap="deptAndUser" parameterType="int">
SELECT * FROM dept where id=#{id}
</select>
<select id="selectUserById2" resultType="com.pkk.entity.User" parameterType="int">
SELECT * FROM USER where deptid=#{deptid}
</select>
</mapper>
5.MyBatis的总配置文件(mybatis-config.xml)
<?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>
<!--指定MyBatis所用的日志具体实现-->
<settings>
<setting name="logImpl" value="LOG4J"/>
<!--lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。默认:true
aggressiveLazyLoading 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--起别名,别名的作用就是用简单明代替全限定类名-->
<typeAliases>
<!--
通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
<package name="com.pkk.entity"/>
-->
<typeAlias alias="user" type="com.pkk.entity.User"/>
</typeAliases>
<!--环境配置,即连接的数据库-->
<environments default="mysql">
<environment id="mysql">
<!--使用jdbc的事务提交与回滚设置-->
<transactionManager type="JDBC"/>
<!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
</dataSource>
</environment>
</environments>
<!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
<mappers>
<!--多表关联查询(全)-->
<mapper resource="com.pkk.test/mappertest/userMapper5.xml"></mapper>
</mappers>
</configuration>
6.测试类以及工具类(工具类见一对一)
package com.pkk.test.association;
import com.alibaba.fastjson.JSONObject;
import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.Map;
/**
* Created by peikunkun on 2018/1/25 0025.
*/
public class AssociationTest1 {
private SqlSession session = null;
@Before
public void before() {
session = TestUtil.getSqlSession();
}
@Test
public void AssociationTest1_38() {
System.out.println("欢迎使用单元测试方法【AssociationTest1_38()】");
System.out.println("此方法测试描述:【一对多的测试】");
List<Dept> depts = session.selectList("com.pkk.test.mappertest.userMapper4.selectDeptById1", 1);
System.out.println(depts);
}
@After
public void end() {
TestUtil.commitAndCloseSession(session);
}
}
7.代码讲解:
注意要点:
1.一对多中一般在只查询一的一方的时候,不需要查询多的一方的时候,这时候我们可以设置懒加载,这样我们就会不用去查询多的一方的信息
2.一对多的关联的集合对象,都应该设置成懒加载3.使用懒加载还需要配置setting,否则无效。
多对一
代码举例参考MyBatis的简单多表关联映射
从下面的图片可以看出,其实一对多和多对一就是站的角度不同,一对多返回的是关联对象是集合对象(配置中用collection),多对一返回的关联对象通常是实体对象(配置中用association )
多对多
订单-商品-用户的关系
订单-用户【多对一】
订单-商品【一对多】
商品-订单【多对多】-【一个商品可以出现多个订单里,多个商品可以出现在一个订单里】
1.创建数据库表
数据库创建说明
用户表:用户体系,有了用户体系才会有开展各种业务可能
订单表:一个用户可以有多个订单
图书表:一个订单中可以包含多本书,一本书也可以在多个订单中选购[多对多]
关联表:主要是为了解决表与表之间多与多的关联,
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL COMMENT '用户名',
`password` varchar(32) DEFAULT NULL COMMENT '用户密码',
`deptid` int(11) DEFAULT NULL COMMENT '部门id',
`cardid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);
CREATE TABLE `m_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(50) DEFAULT NULL COMMENT '订单编码',
`total` int(11) DEFAULT NULL COMMENT '订单总金额(订单总金额是属于订单的属性)',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
PRIMARY KEY (`id`),
KEY `fk_userid` (`user_id`),
CONSTRAINT `fk_userid` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`m_order` (`id`, `code`, `total`, `user_id`) VALUES ('1', 'abcd789456123', '112', '1');
INSERT INTO `mybatis`.`m_order` (`id`, `code`, `total`, `user_id`) VALUES ('2', 'abcdfeh789456123', '674', '1');
CREATE TABLE `m_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT '图书名称',
`price` varchar(11) DEFAULT NULL COMMENT '图书金额',
`remark` varchar(255) DEFAULT NULL COMMENT '图书评价',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('1', 'Spring图书', '56', '不错');
INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('2', 'Hibernate图书', '88', '可以');
INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('3', 'MyBatis图书', '66', '挺好');
CREATE TABLE `m_item` (
`order_id` int(11) NOT NULL DEFAULT '0' COMMENT '订单编号',
`book_id` int(11) NOT NULL DEFAULT '0' COMMENT '图书编号',
`amount` int(11) DEFAULT NULL COMMENT '图书总量(一次订单中一种图书在同一用户下的下单数量)',
PRIMARY KEY (`order_id`,`book_id`),
KEY `book_id` (`book_id`),
CONSTRAINT `m_item_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `m_order` (`id`),
CONSTRAINT `m_item_ibfk_2` FOREIGN KEY (`book_id`) REFERENCES `m_book` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('1', '1', '2');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '1', '3');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '2', '2');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '3', '5');
2.创建实体类(user)
package com.pkk.entity;
import java.io.Serializable;
import java.util.List;
/**
* @author peikunkun
* @version V1.0
* @Title: MyBatisProject
* @Package com.pkk.entity
* @Description: <>
* @date 2017/12/31 19:31
*/
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String cardid;
/*用户与订单是一对多的关系,即一个用户可以有多个订单*/
private List<Order> orders;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public String getCardid() {
return cardid;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", cardid='" + cardid + '\'' +
", orders=" + orders +
'}';
}
}
3.创建实体类(Order)
package com.pkk.entity;
import java.awt.print.Book;
import java.io.Serializable;
import java.util.List;
/**
* Created by peikunkun on 2018/1/26 0026.
*/
public class Order implements Serializable {
private Integer id;
private String code;//订单编号
private Integer total;//订单总金额
/*订单和用户是多对一的关系,即一个订单只属于一个用户*/
private User user;
/*订单和图书是多对多的关系,即一个订单可以是可以包含多个商品,所以返回一个list*/
private List<Book> books;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
@Override
public String toString() {
return "Order{" +
"id=" + id +
", code='" + code + '\'' +
", total=" + total +
", user=" + user +
", books=" + books +
'}';
}
}
4.创建实体类(Book)
package com.pkk.entity;
import java.util.List;
/**
* Created by peikunkun on 2018/1/26 0026.
*/
public class Book {
private Integer id;
private String name;//图书名
private String price;//图书单价
private String remark;//图书说明评价
/*图书和订单是多对多的关系,即一本图书可以存在于多个订单中,所以返回的是List集合*/
private List<Order> orders;
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", price='" + price + '\'' +
", remark='" + remark + '\'' +
", orders=" + orders +
'}';
}
}
5.配置文件(userMapper5.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.pkk.test.mappertest.userMapper5">
<!--***********************************一对多的配置 Begin************************************************-->
<!--本配置文件是针对于多对多的配置文件-->
<!--查询用户的信息,返回的实体映射,包含用户和订单的信息【一对多都是使用的懒加载】 ****第二步-->
<resultMap id="userAndOrder" type="com.pkk.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<collection property="orders" column="id" javaType="ArrayList" ofType="com.pkk.entity.Order"
fetchType="lazy" select="selectOrderByUserId">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="total" column="total"/>
</collection>
</resultMap>
<!--查询用户的信息 ****第一步-->
<select id="selectUserInFoByUserId" resultMap="userAndOrder" timeout="20" parameterType="int">
select * from USER where id =#{id}
</select>
<!--根据用户的id查询订单的信息-->
<select id="selectOrderByUserId" parameterType="int" resultType="com.pkk.entity.Order">
select * from m_order where user_id=#{id}
</select>
<!--***********************************一对多的配置 End************************************************-->
<!--***********************************多对多的配置 Begin************************************************-->
<resultMap id="allInfoByOrder" type="com.pkk.entity.Order">
<!--这里用的是oid,因为在查询的时候使用了别名-->
<id column="oid" property="id"/>
<result column="code" property="code"/>
<result column="total" property="total"/>
<!--多个订单和一个用户的关系-->
<association property="user" column="user_id" javaType="com.pkk.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
</association>
<!--多对多的关联映射{订单}对{图书}-->
<collection property="books" column="oid" javaType="ArrayList" ofType="com.pkk.entity.Book" fetchType="lazy"
select="selectBookByOrderId">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="price" column="price"/>
<result property="remark" column="remark"/>
</collection>
</resultMap>
<!--用户与订单关联,根据订单的id查询出订单和用户的信息-->
<select id="selectOrderById" resultMap="allInfoByOrder" parameterType="int">
select u.*,o.id as oid,o.code,o.total from user u,m_order o where u.id = o.user_id and o.id =#{id}
</select>
<!--依据关联表查询【依据订单查询图书信息】-->
<select id="selectBookByOrderId" timeout="20" parameterType="int" resultType="com.pkk.entity.Book">
select *from m_book b where b.id in (select i.book_id FROM m_item i where i.order_id =#{id})
</select>
<!--***********************************多对多的配置 End************************************************-->
</mapper>
6.总MyBatis配置文件(mybatis-config.xml)
<?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>
<!--指定MyBatis所用的日志具体实现-->
<settings>
<setting name="logImpl" value="LOG4J"/>
<!--lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。默认:true
aggressiveLazyLoading 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--起别名,别名的作用就是用简单明代替全限定类名-->
<typeAliases>
<!--
通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
<package name="com.pkk.entity"/>
-->
<typeAlias alias="user" type="com.pkk.entity.User"/>
</typeAliases>
<!--环境配置,即连接的数据库-->
<environments default="mysql">
<environment id="mysql">
<!--使用jdbc的事务提交与回滚设置-->
<transactionManager type="JDBC"/>
<!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
</dataSource>
</environment>
</environments>
<!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
<mappers>
<!--多表关联查询【多对多】-->
<mapper resource="com.pkk.test/mappertest/userMapper5.xml"></mapper>
</mappers>
</configuration>
7.测试类(测试工具类【同上面的代码示例】)
package com.pkk.test.association;
import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* Created by peikunkun on 2018/1/25 0025.
* 《多对多的关联数据》
*/
public class AssociationTest2 {
private SqlSession session = null;
@Before
public void before() {
session = TestUtil.getSqlSession();
}
@Test
public void AssociationTest1_12() {
System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
System.out.println("此方法测试描述:【一对一的映射关联】");
List<User> users = session.selectList("com.pkk.test.mappertest.userMapper5.selectUserInFoByUserId", 1);
System.out.println(users);
}
@Test
public void AssociationTest1_35() {
System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
System.out.println("此方法测试描述:【一对一的映射关联】");
List<User> users = session.selectList("com.pkk.test.mappertest.userMapper5.selectOrderById", 2);
System.out.println(users);
}
@After
public void end() {
TestUtil.commitAndCloseSession(session);
}
}
8.代码讲解: