Mybatis 44_调用传出参数是游标引用的存储过程

传出参数是游标引用

对于Oracle、PgSQL这种数据库,支持将游标引用作为传出参数。
一般来说,游标往往代表一个结果集,这样可以让存储过程传出多个查询结果集。
当传出参数是游标时,调用该存储过程时,该参数必须使用List类型的变量才能正常封装该结果集。

注意点:

  1. 必须为参数在#{}用mode指定OUT模式。
  2. 传出参数要求必须指定jdbcType,通常指定为CURSOR,PgSQL应该指定为OTHER
    javaType应该指定为ResultSet(当jdbcType=CURSOR,这一步可省略)
    resultMap:它负责将游标引用对应的结果集映射成Java对象。
  3. 当传出参数是游标引用时,该参数必须使用List类型的变量才能正常封装该结果集。
    项目0511游标引用

项目0511游标引用

主类

package lee;

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

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.NewsMapper;
import org.itcheng.app.domain.News;
import org.itcheng.app.domain.NewsWrapper;

public class NewsManager
{
   
	// 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();
		
		// 查询消息
		selectNews(sqlSession);	
		
		//  再次打开SqlSession
		sqlSession = sqlSessionFactory.openSession();
		
		// 查询消息
		selectNews2(sqlSession);	
	}
	
	public static void selectNews(SqlSession sqlSession)
	{
   
		// 此处的NewsMapper只是一个接口
		// MyBatis会使用JDK的动态代理为Mapper接口生成实现类
		NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
		System.out.println(newsMapper.getClass());
		
		Map<String, Object> map = new HashMap<>();
		map.put("id", 1);
		// 调用存储过程。游标类型的传出参数会以key-value对形式放入Map中
		newsMapper.findNewsByProc(map);  // 调用了带传出参数的存储过程
		
		// 取出传出参数对应的值(游标引用封装的结果集)
		List<News> list = (List<News>) map.get("result");
		
		list.forEach(e -> {
   
			System.out.println(e.getContent());
		});
	
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}
	
	public static void selectNews2(SqlSession sqlSession)
	{
   
		// 此处的NewsMapper只是一个接口
		// MyBatis会使用JDK的动态代理为Mapper接口生成实现类
		NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
		System.out.println(newsMapper.getClass());
		
		NewsWrapper nw = new NewsWrapper();
		nw.setId(1); // 该对象的id属性将作为传入参数,
		// newsList属性将作为传出参数,调用存储过程后,newsList属性就封装游标类型的传出参数的值
		newsMapper.findNewsByProc2(nw);  // 调用了带传出参数的存储过程
		
		// 取出传出参数对应的值(游标引用封装的结果集)
		List<News> list = nw.getNewsList();
		
		list.forEach(e -> {
   
			System.out.println(e.getContent());
		});
	
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}	
}

接口类

package org.itcheng.app.dao;

import java.util.Map;

import org.itcheng.app.domain.NewsWrapper;

// Mapper组件相当于DAO组件
public interface NewsMapper
{
   
	void findNewsByProc(Map<String, Object> map);
	
	void findNewsByProc2(NewsWrapper nw);
}

配置文件

<?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属性值相当于该mapper的唯一标识 -->	
<mapper namespace="org.itcheng.app.dao.NewsMapper">

	<select id="findNewsByProc" statementType="CALLABLE">
		<!--
		第二个参数是一个游标引用,因此该参数必须使用List类型的变量
		如果你用Map作为参数传入,第二个result会以key-value对被放入Map参数中,其中key是result,value就是游标引用对应的结果集
		  -->
		{call p_get_news_by_id(#{id}, #{result, mode=OUT, jdbcType=OTHER, javaType=ResultSet, resultMap=newsMap})}
	</select>
	
	<select id="findNewsByProc2" statementType="CALLABLE">
		<!--
		第二个参数是一个游标引用,因此该参数必须使用List类型的变量
		如果你用Map作为参数传入,第二个result会以key-value对被放入Map参数中,其中key是result,value就是游标引用对应的结果集
		  -->
		{call p_get_news_by_id(#{id}, #{newsList, mode=OUT, jdbcType=OTHER, javaType=ResultSet, resultMap=newsMap})}
	</select>	
	
	<resultMap type="news" id="newsMap">
		<id column="news_id" property="id"/>
		<result column="news_title" property="title"/>
		<result column="news_content" property="content"/>
	</resultMap>
</mapper>

对象类

package org.itcheng.app.domain;

public class News
{
   
	private Integer id;
	private String title;
	private String content;
	//有参无参构造器,set和get方法
}
package org.itcheng.app.domain;
import java.util.List;

public class NewsWrapper
{
   
	private Integer id;
	// 该属性用于封装游标引用类型的传出参数
	private List<News> newsList;
	//set和get方法
}

主配置文件

<?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>

 	<typeAliases>
 		<!-- 为指定包下所有类指定别名 -->
 		<package name="org.itcheng.app.domain"/>
 	</typeAliases>
 	
	<!-- 用于配置多个数据库环境 -->
	<environments default="pgsql">
		<!-- environment配置一个数据库环境 -->
		<environment id="pgsql">
			<!-- 配置事务类型:JDBC或Managed,此时的JDBC等都是实现类的缩写 -->
			<transactionManager type="JDBC" />
			<!-- 配置数据库连接池,POOLED也是一个实现类的缩写  -->
			<dataSource type="POOLED">
				<property name="driver" value="org.postgresql.Driver" />
				<property name="url" value="jdbc:postgresql://localhost:5432/mybatis" />
				<property name="username" value="postgres" />
				<property name="password" value="32147" />
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<!-- mapper文件负责管理MyBatis的SQL语句 -->
		<mapper resource="org/itcheng/app/dao/NewsMapper.xml" />
	</mappers>


</configuration>

项目0512游标引用_注解

主配置文件

package lee;

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

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.NewsMapper;
import org.itcheng.app.domain.News;
import org.itcheng.app.domain.NewsWrapper;

public class NewsManager
{
   
	// 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();
		
		// 查询消息
		selectNews(sqlSession);	
		
		//  再次打开SqlSession
		sqlSession = sqlSessionFactory.openSession();
		
		// 查询消息
		selectNews2(sqlSession);				
	}
	
	public static void selectNews(SqlSession sqlSession)
	{
   
		// 此处的NewsMapper只是一个接口
		// MyBatis会使用JDK的动态代理为Mapper接口生成实现类
		NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
		System.out.println(newsMapper.getClass());
		
		Map<String, Object> map = new HashMap<>();
		map.put("id", 1);
		// 调用存储过程。游标类型的传出参数会以key-value对形式放入Map中
		newsMapper.findNewsByProc(map);  // 调用了带传出参数的存储过程
		
		// 取出传出参数对应的值(游标引用封装的结果集)
		List<News> list = (List<News>) map.get("result");
		
		list.forEach(e -> {
   
			System.out.println(e.getContent());
		});
	
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}
	
	public static void selectNews2(SqlSession sqlSession)
	{
   
		// 此处的NewsMapper只是一个接口
		// MyBatis会使用JDK的动态代理为Mapper接口生成实现类
		NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
		System.out.println(newsMapper.getClass());
		
		NewsWrapper nw = new NewsWrapper();
		nw.setId(1); // 该对象的id属性将作为传入参数,
		// newsList属性将作为传出参数,调用存储过程后,newsList属性就封装游标类型的传出参数的值
		newsMapper.findNewsByProc2(nw);  // 调用了带传出参数的存储过程
		
		// 取出传出参数对应的值(游标引用封装的结果集)
		List<News> list = nw.getNewsList();
		
		list.forEach(e -> {
   
			System.out.println(e.getContent());
		});
	
		// 4. 提交事务
		sqlSession.commit();
		// 5. 关闭资源
		sqlSession.close();	
	}	
	
}

接口类

package org.itcheng.app.dao;

import java.util.Map;

import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.StatementType;
import org.itcheng.app.domain.NewsWrapper;

// Mapper组件相当于DAO组件
public interface NewsMapper
{
   
	@Select("{call p_get_news_by_id(#{id}, #{result, mode=OUT, jdbcType=OTHER, javaType=ResultSet, resultMap=newsMap})}")
	@Options(statementType = StatementType.CALLABLE)
	void findNewsByProc(Map<String, Object> map);
	
	@Select("{call p_get_news_by_id(#{id}, #{newsList, mode=OUT, jdbcType=OTHER, javaType=ResultSet, resultMap=newsMap})}")
	@Options(statementType = StatementType.CALLABLE)
	void findNewsByProc2(NewsWrapper nw);
}

配置文件

<?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属性值相当于该mapper的唯一标识 -->	
<mapper namespace="org.itcheng.app.dao.NewsMapper">
	
	<resultMap type="news" id="newsMap">
		<id column="news_id" property="id"/>
		<result column="news_title" property="title"/>
		<result column="news_content" property="content"/>
	</resultMap>
</mapper>

主配置文件

<?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>

 	<typeAliases>
 		<!-- 为指定包下所有类指定别名 -->
 		<package name="org.itcheng.app.domain"/>
 	</typeAliases>
 	
	<!-- 用于配置多个数据库环境 -->
	<environments default="pgsql">
		<!-- environment配置一个数据库环境 -->
		<environment id="pgsql">
			<!-- 配置事务类型:JDBC或Managed,此时的JDBC等都是实现类的缩写 -->
			<transactionManager type="JDBC" />
			<!-- 配置数据库连接池,POOLED也是一个实现类的缩写  -->
			<dataSource type="POOLED">
				<property name="driver" value="org.postgresql.Driver" />
				<property name="url" value="jdbc:postgresql://localhost:5432/mybatis" />
				<property name="username" value="postgres" />
				<property name="password" value="32147" />
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<!-- mapper文件负责管理MyBatis的SQL语句 -->
		<package name="org.itcheng.app.dao" />
	</mappers>


</configuration>

相关推荐

  1. Mybatis 44_调用传出参数游标引用存储过程

    2024-01-21 15:34:02       33 阅读
  2. MyBatis_传入参数问题

    2024-01-21 15:34:02       35 阅读
  3. out参数模式存储过程

    2024-01-21 15:34:02       10 阅读
  4. in参数模式存储过程

    2024-01-21 15:34:02       8 阅读
  5. 创建存储过程,与存储过程调用

    2024-01-21 15:34:02       25 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-21 15:34:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-21 15:34:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-21 15:34:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-21 15:34:02       18 阅读

热门阅读

  1. Gin之gin介绍和安装

    2024-01-21 15:34:02       49 阅读
  2. Ubuntu-MarkText安装使用

    2024-01-21 15:34:02       39 阅读
  3. [go] 迭代器模式

    2024-01-21 15:34:02       32 阅读
  4. MVC的设计理念

    2024-01-21 15:34:02       35 阅读
  5. 野指针(C语言)

    2024-01-21 15:34:02       30 阅读
  6. rust嵌入式之用类函数宏简写状态机定义

    2024-01-21 15:34:02       31 阅读
  7. 小程序定制开发流程

    2024-01-21 15:34:02       35 阅读
  8. HTTP 第二章 发展历史

    2024-01-21 15:34:02       31 阅读
  9. Could not load library libcudnn_cnn_infer.so.8

    2024-01-21 15:34:02       35 阅读
  10. 银行虚拟户和实体账户之间存在一些区别?

    2024-01-21 15:34:02       127 阅读
  11. 系统架构13 - 软件工程(1)

    2024-01-21 15:34:02       33 阅读
  12. 如何使用Webpack打包vue文件

    2024-01-21 15:34:02       30 阅读
  13. Js中的Array.prototype.sort()

    2024-01-21 15:34:02       31 阅读