是否可以在myBatis has_many
中映射嵌套的java.sql.ResultSet
?
例如。假设我有一个像这样定义的过程映射:
resultMap
我的映射器。它返回一个汽车对象列表,还有一个经销商列表(嵌套的CURSOR):
<select id="selectBlog" statementType="CALLABLE">
{call getCarsByYear(
#{year,jdbcType=INTEGER,mode=IN},
#{results, jdbcType=CURSOR, mode=OUT, javaType=java.sql.ResultSet, jdbcType=CURSOR, resultMap=cars}
)}
</select>
问题在于,当我检查生成的java对象时,<resultMap id="cars" type="some.package.Car">
<result property="name" column="car_name">
<!-- here is my problem -->
<collection property="dealerships" column="dealerships_rf" ofType="some.package.Dealership">
<result property="model" column="model" />
<result property="year" column="year" />
</resultMap>
<!-- dealership resultMap of type some.package.Dealership -->
是一个空List。
我写了一些简单的旧java.sql JDBC代码,它运行正常。有人把我放在正确的道路上?我完全迷失了这个。
提前致谢。
这是预期的SQL输出:
dealerships
汽车模型:
Car
|name |dealerships|
|nissan|ref_cursor|
Dealership
|location |established|....
|.... |1974 |...
答案 0 :(得分:7)
我举了一个例子来说明它是如何运作的。
包模型包含两个类:
public class Result {
public int start_from;
public List<Model> models;
}
public class Model {
public int a;
public String b;
}
存储过程
CREATE OR REPLACE PROCEDURE get_data( p_start IN NUMBER
, p_cur OUT SYS_REFCURSOR)
IS
BEGIN
OPEN p_cur FOR
SELECT p_start a,'abc' b FROM dual
UNION ALL
SELECT p_start + 1,'cde' FROM dual
UNION ALL
SELECT p_start + 2,'xyz' FROM dual;
END;
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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="${set_the_url}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis-mapper.xml"/>
</mappers>
</configuration>
<强>的MyBatis-mapper.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">
<resultMap id="map_res_4" type="models.Model">
<result property="a" column="a"/>
<result property="b" column="b"/>
</resultMap>
<parameterMap id="map_par_4" type="models.Result">
<parameter property="start_from" jdbcType="INTEGER" mode="IN" />
<parameter property="models" jdbcType="CURSOR" mode="OUT" resultMap="map_res_4" />
</parameterMap>
<select id="select_4" parameterMap="map_par_4" statementType="CALLABLE">
{CALL get_data(?, ?)}
</select>
</mapper>
使用mybatis调用过程get_data
的示例:
您应注意selectOne
方法返回null,因为我们执行可调用语句。与过程调用的所有交互都使用第二个参数:我们传递start_from
并接收models
作为Result对象的字段(MyBatis可以通过反射获取并设置它们)。所以在方法调用之前和之后Result对象是相同的:你甚至可以将字段设为私有(这里我将它们公开以保持代码更短)。
import models.Result;
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.Reader;
/**
*
*/
public class Main {
private static SqlSessionFactory sessionFactory = null;
private static String CONFIGURATION_FILE = "mybatis-config.xml";
static {
try {
Reader reader = Resources.getResourceAsReader(CONFIGURATION_FILE);
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String... args) {
SqlSession session = sessionFactory.openSession();
Result res = new Result();
res.start_from = 5;
Object obj = session.selectOne("select_4", res);
// `obj` must be NULL
// `res` contains all the results of Oracle procedure call
}
}
答案 1 :(得分:2)
来自ibatis的例子:
<parameter property="result" javaType="java.sql.ResultSet" jdbcType="ORACLECURSOR" mode="OUT"/>
与您的代码的区别:
- javaType was specified
- jdbcType = ORACLECURSOR
中的示例
<sqlMap namespace="KOMUNIKA_REPORT">
<resultMap id="BaseResultMap" class="javaapplication4.StockAreaAndWarehouse" >
<result column="PRODUCT_CODE" property="productCode" />
<result column="PRODUCT_NAME" property="productName" />
<result column="INCOMING" property="incoming" />
<result column="UNIT_SOLD" property="unitSold" />
<result column="TOTAL_STOCK" property="totalStock" />
</resultMap>
<parameterMap id="resultMap" class="java.util.Map">
<parameter property="result" javaType="java.sql.ResultSet" jdbcType="ORACLECURSOR" mode="OUT"/>
</parameterMap>
<procedure id="selectStockAreaAndWarehouse"
parameterMap="resultMap"
resultMap="BaseResultMap"
>
{ call KOMUNIKA.LP_STOCK_AREA_WAREHOUSE(?) }
</procedure>
</sqlMap>
<resultMap id="userDataResultMap" type="TestUserData">
<id property="userid" column="userid" />
<result property="firstName" column="firstName"/>
<result property="lastName" column="lastName"/>
<result property="zip" column="zip"/>
<result property="summary" column="summary"/>
<result property="specialities" column="specialities"/>
<result property="isActive" column="isActive"/>
<result property="country" column="country"/>
<result property="platform" column="platforms"/>
</resultMap>
<select id="getFullPublicData" statementType="CALLABLE" parameterType="User" >
{call p_user_public_data(#{userId}
,#{userDataList,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet, resultMap=com.test.data.UserPublicViewMapper.userDataResultMap}
,#{noOfConnections,mode=OUT,jdbcType=NUMERIC,javaType=int}
,#{noOfRecommendations,mode=OUT,jdbcType=NUMERIC,javaType=int})}
</select>