【问题标题】:Calling Oracle stored procedures with MyBatis用 MyBatis 调用 Oracle 存储过程
【发布时间】:2013-03-18 00:09:33
【问题描述】:

我正在将我们的数据库从 SQL Server 2008 迁移到 Oracle,但无法让 MyBatis 工作。

举个例子:

UserMapper.xml(示例)

<resultMap type="User" id="UserResult">
    <id property="userId" column="userId"/>
    <result property="firstName" column="firstName"/>
    <result property="lastName" column="lastName"/>
</resultMap>

<select id="getUsers" statementType="CALLABLE" resultMap="UserResult">
    {CALL GetUsers()}
</select>

UserDAO.java

public interface UserDAO {
    public List<User> getUsers();
}

SQL Server 过程

CREATE PROCEDURE [dbo].[GetUsers]
AS
BEGIN
    SET NOCOUNT ON;
    SELECT userId, firstName, lastName
    FROM Users
END

...在 SQL Server 2008 中工作。有人可以向我解释如何从 UserMapper.xml 调用 Oracle 过程(与上面的 SQL Server 过程具有相同的名称和列)并填充我的 User 类Oracle 游标?

这是我尝试过的:

<resultMap type="User" id="UserResult">
    <id property="userId" column="userId"/>
    <result property="firstName" column="firstName"/>
    <result property="lastName" column="lastName"/>
</resultMap>

<select id="getUsers" statementType="CALLABLE" resultMap="UserResult">
    {CALL GetUsers(#{resultSet,mode=OUT,jdbcType=CURSOR,resultMap=UserResult})}
</select>

我得到这个错误:

Caused by: org.apache.ibatis.reflection.ReflectionException: 
Could not set property 'resultSet' of 'class java.lang.Class'
with value 'oracle.jdbc.driver.OracleResultSetImpl@476d05dc' 
Cause: org.apache.ibatis.reflection.ReflectionException: 
There is no setter for property named 'resultSet' in 'class java.lang.Class'

【问题讨论】:

    标签: java oracle mybatis ibatis database-cursor


    【解决方案1】:

    结果图如下所示:

    <resultMap id="UserResult" type="User">
        <id property="userId" column="userId"/>
        <result property="firstName" column="firstName"/>
        <result property="lastName" column="lastName"/>     
    </resultMap>
    

    在您的 select 语句中,将参数类型更改为 java.util.Map。

    <select id="getUsers" statementType="CALLABLE" parameterType="java.util.Map"> 
        {call GetUsers(#{users, jdbcType=CURSOR, javaType=java.sql.ResultSet, mode=OUT, resultMap=UserResult})} 
    </select>
    

    您的映射器界面看起来像这样,看起来您当前正在将其称为 DAO。我过去的做法是制作一个映射器接口,该接口被注入到 DAO 中,而 DAO 是调用映射器上的方法的东西。这是一个示例映射器接口:

    public interface UserMapper {
        public Object getUsers(Map<String, Object> params);
    }
    

    然后该映射器类将被注入 DAO 类并像这样进行调用:

    public List<User> getUsers() {
        Map<String, Object> params = new HashMap<String, Object>(); 
        ResultSet rs = null;
        params.put("users", rs);
        userMapper.getUsers(params);
        return ((ArrayList<User>)params.get("users"));
    }
    

    【讨论】:

    • 谢谢 clav。我试过你的例子,我得到了与上面第 2 行相同的错误:“Could not set property 'resultSet' of 'class java.lang.Class'。”有什么想法吗?
    • 我不记得确切的语法了。我感觉到你对这个的痛苦,因为我大约一年前经历过它。我找到了一些我保留的示例代码并更新了我的答案,试一试。
    • 太棒了。非常感谢您的回答,应该是谷歌搜索“无法设置类 java.lang.Class 的属性”的第一件事。谢谢谢谢谢谢!
    • @clav 你是一个英雄(如果你是女性,你是女英雄)。我花了一整天的时间试图找到这个解决方案。这非常有效。
    【解决方案2】:

    使用 MyBatis/iBATIS 3 从 Oracle 11 获取结果集是一个非常奇怪的过程。这对我来说毫无意义,但它奏效了。我的例子不同,但你会明白的:

    create or replace 
    PROCEDURE SP_GET_ALL_STORED_PROC (l_cursor out SYS_REFCURSOR) IS
    BEGIN
    open l_cursor for select account_id, totalLegs, born, weight, mammal, animal from copybittest;
    END SP_GET_ALL_STORED_PROC;
    
    Map map = new HashMap();
    session.selectList("ibatis_3_test.selectProductAllOracleStoredProc", map); 
    List productList = (List) map.get("key");
    
    <resultMap id="productResultMap" type="test.Product">
    </resultMap>
    
    <select id="selectProductAllOracleStoredProc" parameterType="java.util.Map" statementType="CALLABLE">
        {call SP_GET_ALL_STORED_PROC(#{key, jdbcType=CURSOR, mode=OUT, javaType=java.sql.ResultSet,resultMap=productResultMap})}
    </select>
    

    【讨论】:

      【解决方案3】:

      只是对clav的注释的补充,Snoozy,你需要从

      中移除resultSet
      <select id="getUsers" statementType="CALLABLE" resultMap="UserResult">
          {CALL GetUsers(#    {resultSet,mode=OUT,jdbcType=CURSOR,resultMap=UserResult})}
      

      并将其更改为“key”,如下所示:

      <select id="getUsers" statementType="CALLABLE" resultMap="UserResult">
          {CALL GetUsers(#{key,mode=OUT,jdbcType=CURSOR,resultMap=UserResult})}
      </select>
      

      希望对您有所帮助。

      【讨论】:

        【解决方案4】:

        我也遇到了同样的错误。

        引起:org.apache.ibatis.reflection.ReflectionException:有 'class java.lang.Class' 中没有名为 'columnNames' 的属性的设置器

        在 mapper.java 中 getSearchResult(searchCriteriaVO vo)

        在 mapper.xml 中

          #{userId, mode=IN, jdbcType=VARCHAR},
            #{resultList, mode=OUT, jdbcType=CURSOR, javaType=ResultSet,  resultMap=inquiryResult},
        

        inquiryResult 定义为

        <resultMap type="java.util.LinkedHashMap" id="inquiryResult">
        <result property="name" jdbcType="VARCHAR" javaType="String" column="name"/>
        

        挣扎了一天 但是当我调试时,这是我犯的一个简单的错误。我的值对象作为 null 传递给我的映射器类。即使我的 VO 为空,查询也会被执行,因为 mybatis 将值传递为空。但是当mybatis试图将结果设置为我的VO时,由于它为null,所以抛出了上述错误。

        希望这是有用的信息

        【讨论】:

          猜你喜欢
          • 2014-05-26
          • 1970-01-01
          • 2015-11-02
          • 1970-01-01
          • 1970-01-01
          • 2021-10-31
          • 2020-02-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多