spring中的关联映射
- mybatis的映射关系
- 一对一
- 加载关联对象的两种方式
- 代码
- IdCard
- Person
- IdCardMapper.xml
- PersonMapper.xml
- MyBatisUtils
- mybatis-config.xml
- Test
- Test1
- 数据库的表
- 一对多的关联映射
- 数据库中的表
- User
- Orders
- UserMapper.xml
- mybatis-config.xml
- Test2
- 多对多
- 数据库
- Orders
- Product
- OrdersMapper.xml
- ProductMapper.xml
- Test3
- mybatis-config.xml
mybatis的映射关系
- 在开发中对数据库操作经常用到多张表,这在面向对象中涉及到对象与对象之间的关联关系,而mybatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关系,
- 在关系型数据库中,多表之间存在着三种关联关系,分别为一对一,一对多,多对多,
- 在java中,通过对象也可以进行关联关系描述,如下图所示,
一对一
在mybatis中怎末解决一对一的问题呢,在resultMpa元素中包含一个assocation的子元素,通过它可以处理一对一的关联关系
- associatin元素中属性
- property:指定映射到实体类对象属性,与表字段一一对应。
- column:指定表中对应的字段
- javaType:指定映射到实体对象属性的类型
- select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询
- fetchType:指定在关联查询时是否启用延迟加载,该属性由lazy和eager两个属性值,默认值时lazy(即默认关联映射延迟加载)
加载关联对象的两种方式
- 嵌套查询和嵌套结果
代码
IdCard
package com.yzb.chapter09;
public class IdCard {
private Integer id;
private String code;
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;
}
@Override
public String toString() {
return "IdCard{" +
"id=" + id +
", code='" + code + '\'' +
'}';
}
}
Person
package com.yzb.chapter09;
public class Person {
private Integer id;
private String name;
private Integer age;
private String sex;
private IdCard card;//个人关联的证件
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public IdCard getCard() {
return card;
}
public void setCard(IdCard card) {
this.card = card;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", card=" + card +
'}';
}
}
IdCardMapper.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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.yzb.chapter09.IdCardMapper">
<!--根据id查询证件信息-->
<select id="findCodeById" parameterType="Integer" resultType="com.yzb.chapter09.IdCard">
select * from tb_idcard where id = #{id}
</select>
</mapper>
PersonMapper.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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.yzb.chapter09.PersonMapper">
<!--嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
<select id="findPersonById" parameterType="Integer" resultMap="IdCardWithPersonResult">
select * from tb_person where id= #{id}
</select>
<resultMap id="IdCardWithPersonResult" type="com.yzb.chapter09.Person">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<!--使用一对一:assocation使用select属性引入另一条SQL语句-->
<!--property指定的是Person类中定义的IdCard类型的属性名,column是定义在与person对应的数据库表中的IdCard的引入的主键 javaType对应的是映射的IdCard类的-->
<association property="card" column="card_id" javaType="com.yzb.chapter09.IdCard" select="com.yzb.chapter09.IdCardMapper.findCodeById">
</association>
</resultMap>
<!--嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
<select id="findPersonById2" parameterType="Integer" resultMap="IdCardWithPersonResult2">
select p.*,idcard.code from tb_person p ,tb_idcard idcard where p.card_id = and = #{id}
</select>
<resultMap id="IdCardWithPersonResult2" type="com.yzb.chapter09.Person">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<association property="card" javaType="com.yzb.chapter09.IdCard">
<id property="id" column="card_id"/>
<result property="code" column="code"/>
</association>
</resultMap>
</mapper>
MyBatisUtils
package com.yzb.chapter09;
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 java.io.IOException;
import java.io.InputStream;
/*
* 工具类
* */
public class MyBatisUtils {
/*
* 初始化sqlSessionFactory对象
* */
private static SqlSessionFactory sqlSessionFactory = null;
static {
try {
//使用mybatis提供resources类加载MyBatis的配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession对象的方法
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
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>
<settings>
<!--打开延迟加载的开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为延迟加载,即按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--1.配置环境 ,默认的环境id为mysql-->
<environments default="mysql">
<!--1.2.配置id为mysql的数据库环境 -->
<environment id="mysql">
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC" />
<!--数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/spring" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!--2.配置Mapper的位置 -->
<mappers>
<mapper resource="com/yzb/chapter09/IdCardMapper.xml" />
<mapper resource="com/yzb/chapter09/PersonMapper.xml"/>
</mappers>
</configuration>
Test
package com.yzb.chapter09;
import org.apache.ibatis.session.SqlSession;
/*
* MyBatis关联查询映射测试类
* */
public class Test {
/*
* 嵌套查询
* */
public static void main(String[] args) {
//通过工具类生成sqlSession对象
SqlSession session = MyBatisUtils.getSession();
//执行查询
Person p = session.selectOne("com.yzb.chapter09.PersonMapper.findPersonById",1);
System.out.println(p);
/*当开启延迟加载的时候,这时只需要加载Person的数据库的SQL语句查询就可以了*/
System.out.println(p.getName());
//关闭SqlSession对象
session.close();
}
}
Test1
package com.yzb.chapter09;
import org.apache.ibatis.session.SqlSession;
/*
* MyBatis关联查询映射测试类
* */
public class Test1 {
/*
* 嵌套结果
* */
public static void main(String[] args) {
//通过工具类生成sqlSession对象
SqlSession session = MyBatisUtils.getSession();
//执行查询
Person p = session.selectOne("com.yzb.chapter09.PersonMapper.findPersonById2",1);
System.out.println(p);
//关闭SqlSession对象
session.close();
}
}
数据库的表
tb_person
tb_IcCard
一对多的关联映射
在resultMap元素中使用collection的子元素,使用collection元素完成一对多的关联映射,子元素与association元素相同,但ofType与javaType属性相对应。它用于指定实体对象中集合类型属性包含的元素类型。
数据库中的表
tb_User
tb_orders
User
package com.yzb.chapter09.example;
import java.util.List;
public class User {
private Integer id;
private String username;
private String address;
private List<Orders> ordersList;//用户关联的订单
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", ordersList=" + ordersList +
'}';
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Orders> getOrdersList() {
return ordersList;
}
public void setOrdersList(List<Orders> ordersList) {
this.ordersList = ordersList;
}
}
Orders
package com.yzb.chapter09.example;
public class Orders {
private Integer id;
private String number;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "Orders{" +
"id=" + id +
", number='" + number + '\'' +
'}';
}
}
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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.yzb.chapter09.example.UserMapper">
<!--一对多,查看某一用户及其关联的订单信息-->
<!--当关联出来的列名相同时,需要使用别名来区分-->
<select id="findUserWithOrders" resultMap="UserWithOrdersResult" parameterType="Integer">
select u.* , as order_id ,o.number from tb_user u,tb_orders o where u.id=o.user_id and u.id =#{id}
</select>
<resultMap id="UserWithOrdersResult" type="com.yzb.chapter09.example.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
<!--一对多关联映射,collection
ofType表示属性集合元素的类型,List<Orders>属性即Orders类-->
<collection property="ordersList" ofType="com.yzb.chapter09.example.Orders">
<id property="id" column="order_id"></id>
<result property="number" column="number"></result>
</collection>
</resultMap>
</mapper>
mybatis-config.xml
<!--2.配置Mapper的位置 -->
<mappers>
<mapper resource="com/yzb/chapter09/IdCardMapper.xml" />
<mapper resource="com/yzb/chapter09/PersonMapper.xml"/>
<mapper resource="com/yzb/chapter09/example/UserMapper.xml"/>
</mappers>
Test2
package com.yzb.chapter09.example;
import com.yzb.chapter09.MyBatisUtils;
import com.yzb.chapter09.Person;
import org.apache.ibatis.session.SqlSession;
/*
* MyBatis关联查询映射测试类
* */
public class Test2 {
/*
* 嵌套查询
* */
public static void main(String[] args) {
//通过工具类生成sqlSession对象
SqlSession session = MyBatisUtils.getSession();
//执行查询
User user= session.selectOne("com.yzb.chapter09.example.UserMapper.findUserWithOrders",1);
System.out.println(user);
//关闭SqlSession对象
session.close();
}
}
多对多
数据库
CREATE TABLE tb_product (
id INT(32) PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR (32),
price DOUBLE
);
INSERT INTO tb_product VALUES('1','Java基础入门','11.0');
INSERT INTO tb_product VALUES('2','Spring','45.0');
INSERT INTO tb_product VALUES('3','JavaWeb','78.0');
CREATE TABLE tb_ordersitem (
id INT(32) PRIMARY KEY AUTO_INCREMENT,
orders_id INT(32),
product_id INT (32),
FOREIGN KEY(orders_id) REFERENCES tb_orders(id),
FOREIGN KEY(product_id) REFERENCES tb_product(id),
)
INSERT INTO tb_ordersitem VALUES('1','1','1');
INSERT INTO tb_ordersitem VALUES('2','1','3');
INSERT INTO tb_ordersitem VALUES('2','3','3');
Orders
package com.yzb.chapter09.example;
import java.util.List;
public class Orders {
private Integer id;
private String number;
private List<Product> productList;
public List<Product> getProductList() {
return productList;
}
public void setProductList(List<Product> productList) {
this.productList = productList;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "Orders{" +
"id=" + id +
", number='" + number + '\'' +
", productList=" + productList +
'}';
}
}
Product
package com.yzb.chapter09.example;
import java.util.List;
/*
* 商品持久层
* */
public class Product {
private Integer id;
private String name;
private Double price;
private List<Orders> orders;
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
", 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) {
= name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
}
OrdersMapper.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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.yzb.chapter09.example.OrdersMapper">
<!--多对多镶嵌查询:通过执行另一条SQL映射语句来返回预期的特殊类型-->
<select id="findOrdersWithProduct" parameterType="Integer" resultMap="OrdersWithProductResult">
select * from tb_orders where id= #{id}
</select>
<resultMap id="OrdersWithProductResult" type="com.yzb.chapter09.example.Orders">
<id property="id" column="id"></id>
<result column="number" property="number"></result>
<collection property="productList" column="id" ofType="com.yzb.chapter09.example.Product" select="com.yzb.chapter09.example.UserMapper.findProductById">
</collection>
</resultMap>
<!--多对多镶嵌结果:通过执行另一条SQL映射语句来返回预期的特殊类型-->
<select id="findOrdersWithProduct1" parameterType="Integer" resultMap="OrdersWithProductResult1">
select o.*, as pid,,p.price,form tb_orders o,tb_product p ,tb_ordersitem oi where oi.orders_id = and oi.product_id= and =#{id}
</select>
<!--自定义手动映射类型-->
<resultMap id="OrdersWithProductResult1" type="com.yzb.chapter09.example.Orders">
<id property="id" column="id"></id>
<result column="number" property="number"></result>
<!--多对多关联映射:collection-->
<collection property="productList" ofType="com.yzb.chapter09.example.Product" >
<id property="id" column="pid"/>
<result property="name" column="name"/>
<result property="price" column="price"/>
</collection>
</resultMap>
</mapper>
ProductMapper.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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.yzb.chapter09.example.UserMapper">
<!--多对多镶嵌查询-->
<select id="findProductById" parameterType="Integer" resultType="com.yzb.chapter09.example.Product">
select * from tb_product where id in (select product_id from tb_ordersitem where orders_id =#{id})
</select>
</mapper>
Test3
package com.yzb.chapter09.example;
import com.yzb.chapter09.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
/*
* MyBatis关联查询映射测试类
* */
public class Test3 {
/*
* 嵌套查询
* */
public static void main(String[] args) {
//通过工具类生成sqlSession对象
SqlSession session = MyBatisUtils.getSession();
//执行查询
Orders orders = session.selectOne("com.yzb.chapter09.example.OrdersMapper.findOrdersWithProduct",1);
System.out.println(orders);
//关闭SqlSession对象
session.close();
}
}
mybatis-config.xml
<mappers>
<mapper resource="com/yzb/chapter09/IdCardMapper.xml" />
<mapper resource="com/yzb/chapter09/PersonMapper.xml"/>
<mapper resource="com/yzb/chapter09/example/UserMapper.xml"/>
<mapper resource="com/yzb/chapter09/example/ProductMapper.xml"/>
<mapper resource="com/yzb/chapter09/example/OrdersMapper.xml"/>
</mappers>