Mybatis 51_基于多表连接查询和基于多结果集的1-N关联

51_基于多表连接查询和基于多结果集的1-N关联

  • 基于多表连接查询的1-N关联映射(不可能延迟加载)
    • 基于多表连接的关联映射时,关键是指定如下独有属性:
    • 项目0520基于多表连接查询的1-N
  • 多结果集的1-N关联映射
    • 要修改的地方
    • 项目0521多结果集的1-N

基于多表连接查询的1-N关联映射(不可能延迟加载)

多表连接:一次查询获取对象及其关联对象的数据,然后将它们映射成对象及其关联的对象。
这种方式主要执行一次查询即可。
当关联实体是N时,使用元素来映射关联实体。

基于多表连接的关联映射时,关键是指定如下独有属性:

  - resultMap: 再次指定一个映射对象对关联实体执行映射
  - columnPrefix:指定使用列前缀进行区分。
  - autoMapping:指定是否使用自动映射
  - notNullColumn:默认情况,只要关联实体的任意列不为null,都会创建关联实体。
                   如果指定了该属性,只要当该属性所指定的全部列不为null,才会创建关联实体。

项目0520基于多表连接查询的1-N

主类

package lee;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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.itcheng.app.dao.AddressMapper;
import org.itcheng.app.dao.PersonMapper;
import org.itcheng.app.domain.Address;
import org.itcheng.app.domain.Person;

public class PersonManager
{
	// SqlSessionFactory应该是应用级别
	private static SqlSessionFactory sqlSessionFactory;
	public static void main(String[] args) throws IOException
	{
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 1. 创建SqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		// 2. 打开SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		
//		findPerson(sqlSession);
		/* 结果
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson ==>  Preparing: select p.*, ad.* from person_inf p join address_inf ad on ad.owner_id = p.person_id where person_id = ? 
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson ==> Parameters: 3(Integer)
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson <==      Total: 2
		 * 白素贞
		 * -----------------
		 * 陷空山无底洞
		 * 灵山大雷音寺
		 * */
	
		findAddresses(sqlSession);
		/* 结果
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById ==>  Preparing: select ad.*, p.* from address_inf ad join person_inf p on ad.owner_id = p.person_id where addr_id > ? 
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById ==> Parameters: 3(Integer)
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById <==      Total: 6
		 * 斜月三星洞-->法海
		 * 福陵山云栈洞-->小青
		 * 高老庄-->小青
		 * 陷空山无底洞-->白素贞
		 * 灵山大雷音寺-->白素贞
		 * 积雷山摩云洞-->玉面狐狸
		 * -----------------
		 * */
	}
	
	public static void findPerson(SqlSession sqlSession)
	{
		PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
		
		Person p = personMapper.getPerson(3);
		System.out.println(p.getName());
		System.out.println("-----------------");
		
		// Person获取关联实体是延迟加载,要等到真正访问关联实体时才去执行额外的SELECT语句
		List<Address> addresses = p.getAddresses();
		addresses.forEach(e -> {
			System.out.println(e.getDetail());
		});
		
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}
	
	public static void findAddresses(SqlSession sqlSession)
	{
		AddressMapper addressMapper = sqlSession.getMapper(AddressMapper.class);
		
		List<Address> addrList = addressMapper.findAddressesById(3);
		//  由于Address获取关联实体是立即加载,因此它会立即执行额外的SELECT语句
		// 对于立即加载策略,即使不访问关联实体,它也会立即执行额外的SELECT语句
		addrList.forEach(e -> {
			System.out.println(e.getDetail() + "-->" + e.getPerson().getName());
		});
		System.out.println("-----------------");
		
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}	
		
}

接口类

package org.itcheng.app.dao;
import java.util.List;

import org.itcheng.app.domain.Address;

// Mapper组件相当于DAO组件
public interface AddressMapper
{
	List<Address> findAddressesById(Integer id);
}
package org.itcheng.app.dao;
import org.itcheng.app.domain.Person;

// Mapper组件相当于DAO组件
public interface PersonMapper
{
	Person getPerson(Integer id);
}

配置文件


DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<mapper namespace="org.itcheng.app.dao.AddressMapper">

	<select id="findAddressesById" resultMap="addrMap">
		select ad.*, p.* 
		from address_inf ad
		join person_inf p
		on ad.owner_id = p.person_id
		where addr_id > #{id}
	select>

	<resultMap type="address" id="addrMap">
		<id column="addr_id" property="id"/>
		<result column="addr_detail" property="detail"/>
			
		<association property="person" 
			resultMap="org.itcheng.app.dao.PersonMapper.personMap" />
	resultMap>
mapper>

DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<mapper namespace="org.itcheng.app.dao.PersonMapper">
	<select id="getPerson" resultMap="personMap">
		select 
		p.*, ad.*
		from person_inf p
		join address_inf ad
		on ad.owner_id = p.person_id
		where person_id = #{id}
	select>
	
	<resultMap type="person" id="personMap">
		<id column="person_id" property="id"/>
		<result column="person_name" property="name"/>
		<result column="person_age" property="age"/>
			
		<collection property="addresses" 
			javaType="ArrayList"
			ofType="address"
			resultMap="org.itcheng.app.dao.AddressMapper.addrMap"/>
	resultMap>
mapper>

多结果集的1-N关联映射

这种情况比较少见:它要求执行一次数据库查询,就能返回多个结果集。
通常表现为调用存储过程——调用一次,可能返回多个结果集

要修改的地方

  1. SQL语句改为调用存储过程,不再是执行简单的select语句
  2. 元素中使用resultSets为多个结果集指定了名字。
    【注意】: resultSets为多个结果集指定名称时,名称之间只能有逗号分隔符,不能有额外的空格
  3. 元素或中指定如下4个属性(前3个是特有的):
    • column:指定当前表中用于记录关联关系的数据列的列名。
    • foreignColumn:指定关联表中用于记录关联关系的数据列的列名。
    • resultSet: 用哪个结果集来执行映射
    • resultMap:还是同样指定。

项目0521多结果集的1-N

主类

package lee;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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.itcheng.app.dao.AddressMapper;
import org.itcheng.app.dao.PersonMapper;
import org.itcheng.app.domain.Address;
import org.itcheng.app.domain.Person;

public class PersonManager
{
	// SqlSessionFactory应该是应用级别
	private static SqlSessionFactory sqlSessionFactory;
	public static void main(String[] args) throws IOException
	{
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 1. 创建SqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		// 2. 打开SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		
//		findPerson(sqlSession);
		/* 结果
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson ==>  Preparing: {call p_get_person_address(?)} 
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson ==> Parameters: 2(Integer)
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson <==      Total: 1
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson <==      Total: 2
		 * DEBUG [main] org.itcheng.app.dao.PersonMapper.getPerson <==    Updates: 0
		 * 小青
		 * -----------------
		 * 福陵山云栈洞
		 * 高老庄
		 * */
	
		findAddresses(sqlSession);
		/* 结果
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById ==>  Preparing: {call p_get_address_person(?)} 
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById ==> Parameters: 3(Integer)
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById <==      Total: 6
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById <==      Total: 4
		 * DEBUG [main] org.itcheng.app.dao.AddressMapper.findAddressesById <==    Updates: 0
		 * 斜月三星洞-->法海
		 * 福陵山云栈洞-->小青
		 * 高老庄-->小青
		 * 陷空山无底洞-->白素贞
		 * 灵山大雷音寺-->白素贞
		 * 积雷山摩云洞-->玉面狐狸
		 * -----------------
		 * */
	}
	
	public static void findPerson(SqlSession sqlSession)
	{
		PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
		
		Person p = personMapper.getPerson(2);
		System.out.println(p.getName());
		System.out.println("-----------------");
		
		// Person获取关联实体是延迟加载,要等到真正访问关联实体时才去执行额外的SELECT语句
		List<Address> addresses = p.getAddresses();
		addresses.forEach(e -> {
			System.out.println(e.getDetail());
		});
		
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}
	
	public static void findAddresses(SqlSession sqlSession)
	{
		AddressMapper addressMapper = sqlSession.getMapper(AddressMapper.class);
		
		List<Address> addrList = addressMapper.findAddressesById(3);
		//  由于Address获取关联实体是立即加载,因此它会立即执行额外的SELECT语句
		// 对于立即加载策略,即使不访问关联实体,它也会立即执行额外的SELECT语句
		addrList.forEach(e -> {
			System.out.println(e.getDetail() + "-->" + e.getPerson().getName());
		});
		System.out.println("-----------------");
		
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}
}

接口类

package org.itcheng.app.dao;
import java.util.List;
import org.itcheng.app.domain.Address;
// Mapper组件相当于DAO组件
public interface AddressMapper
{
	List<Address> findAddressesById(Integer id);
}
package org.itcheng.app.dao;
import org.itcheng.app.domain.Person;
// Mapper组件相当于DAO组件
public interface PersonMapper
{
	Person getPerson(Integer id);
}

配置文件


DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<mapper namespace="org.itcheng.app.dao.AddressMapper">

	<select id="findAddressesById" resultMap="addrMap" statementType="CALLABLE"
		resultSets="addrs,persons">
		{call p_get_address_person(#{id, mode=IN, jdbcType=INTEGER})}
	select>

	<resultMap type="address" id="addrMap">
		<id column="addr_id" property="id"/>
		<result column="addr_detail" property="detail"/>
		
		<association property="person" 
			column="owner_id"
			foreignColumn="person_id"
			resultSet="persons"
			resultMap="org.itcheng.app.dao.PersonMapper.personMap" />
	resultMap>
	
mapper>

DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<mapper namespace="org.itcheng.app.dao.PersonMapper">
	<select id="getPerson" resultMap="personMap" statementType="CALLABLE"
		resultSets="persons,addrs">
		{call p_get_person_address(#{id})}
	select>
	
	<resultMap type="person" id="personMap">
		<id column="person_id" property="id"/>
		<result column="person_name" property="name"/>
		<result column="person_age" property="age"/>
				
		<collection property="addresses"
			column="person_id" foreignColumn="owner_id"
			resultSet="addrs"
			resultMap="org.itcheng.app.dao.AddressMapper.addrMap"/>
	resultMap>
mapper>

你可能感兴趣的:(mybatis,java,eclipse,mysql,数据库)