2012-02-22 23 views
1

データベース操作にEntityManagerを使用しています。このEntityManagerを使用してストアドプロシージャを実行します。私はプロシージャを実行するために以下のコードを使用していますが、のためにを登録する方法がわかりません。javax.persistence.EntityManagerを使用してストアドプロシージャの出力パラメータを登録する

 Query query = appsEntityManager.createNativeQuery("{call test(?,?,?)}"); 
     query.setParameter(1, ""); 
     query.setParameter(2, ""); 
     query.setParameter(3, ""); 
     query.getResultList(); 

これを解決するのを手伝ってください。 この問題を解決する方法はありませんか?

答えて

6

この実装を試してみてください:

はあなたEntityManagerを使用してjava.sql.Connectionを取得します。

Connection cc = ((SessionImpl) em.getDelegate()).connection(); 

このConnectionを使用すると、この方法によって、ストアドプロシージャや関数への呼び出しを行うためにjava.sql.CallableStatementクラスを使用することができます。

CallableStatement callableStatement; 

try { 
    callableStatement = cc.prepareCall("{call stored_proc(?,?,?,?,?)}"); 

    callableStatement.setString(1, "1");//Parameter #1 
    callableStatement.setString(2, "ET");////Parameter #2 
    callableStatement.setString(3, "|s|");// //Parameter #3 
    callableStatement.registerOutParameter(4, Types.INTEGER); //Output # 1 
    callableStatement.registerOutParameter(5, Types.VARCHAR); //Output # 2 
    callableStatement.execute(); 

    Integer outputValue = callableStatement.getInt(4); 
    String outputValue1 = callableStatement.getString(5); 
} 

もう1つの実装は、これに基づいています。post
StoredProcedureを拡張するクラスを作成します。

/** 
* Class to provide access to the database. With this class you can invoke functions and stored procedures. 
*/ 
public class GenericDatabaseCaller { 

    /**Data source. */ 
    private DataSource dataSource; 

    /** 
    * This method requires LinkedHashMaps for inParams and outParams so that parameters can be set in a 
    * sequence. 
    * @param functionName Name of the stored procedure or function. 
    * @param isFunction indicates if the process to execute is a Function or a Stored procedure. 
    * @param inParams {@link LinkedHashMap} of IN parameters. 
    * @param outParams {@link LinkedHashMap} of OUT Parameters. 
    * @return {@link Map} with the output parameters. 
    */ 
    public Map executeSimpleProcedure(String functionName, boolean isFunction, Map<String, Object> inParams, 
     Map<String, Object> outParams) { 
    InnerStoredProcedure innerStoredProcedure = new InnerStoredProcedure(dataSource, functionName, isFunction, 
     inParams, outParams); 
    return innerStoredProcedure.executeProcedure(inParams); 
    } 

    private class InnerStoredProcedure extends StoredProcedure { 

    /** 
    * @param ds 
    * @param SQL 
    * @param isFunction 
    * @param inParams 
    * @param outParams 
    */ 
    public InnerStoredProcedure(DataSource ds, String SQL, boolean isFunction, Map<String, Object> inParams, Map<String, Object> outParams) { 
     setDataSource(ds); 
     setFunction(isFunction); 
     setSql(SQL); 
     configerParameters(inParams, outParams); 
     compile(); 
    } 

    /** 
    * Configure the input and output parameters for the stored procedure 
    * @param inParams 
    * @param outputParamers 
    */ 
    public void configerParameters(Map<String, Object> inParams, Map<String, Object> outputParamers) { 
     if (inParams != null && inParams.size() > 0) { 
     Iterator<String> keySetIterator = inParams.keySet().iterator(); 
     while (keySetIterator.hasNext()) { 
      String key = keySetIterator.next(); 
      if (inParams.get(key) instanceof String) { 
      declareParameter(new SqlParameter(key, Types.VARCHAR)); 
      } else if (inParams.get(key) instanceof Integer) { 
      declareParameter(new SqlParameter(key, Types.INTEGER)); 
      } else if (inParams.get(key) instanceof Date || inParams.get(key) instanceof java.sql.Date) { 
      declareParameter(new SqlParameter(key, Types.DATE)); 
      } 
      // TODO Add more types. 
     } 
     } 

     if (outputParamers != null && outputParamers.size() > 0) { 
     Iterator<String> keySetIterator = outputParamers.keySet().iterator(); 
     while (keySetIterator.hasNext()) { 
      String key = keySetIterator.next(); 
      if (outputParamers.get(key) instanceof String) { 
      declareParameter(new SqlOutParameter(key, Types.VARCHAR)); 
      } else if (outputParamers.get(key) instanceof Integer) { 
      declareParameter(new SqlOutParameter(key, Types.INTEGER)); 
      } 
     } 
     } 
    } 

    public Map executeProcedure(Map inputs) { 

     return execute(inputs); 
    } 
    } 
} 

その後、あなたはあなたの関数やストアドプロシージャを呼び出すことができます:GenericDatabaseCallerをインスタンス化するに

String procedureName = "stored_proc"; 

Map<String, Object> inMap = new LinkedHashMap<String, Object>(); 
inMap.put("parameter1", "10"); 
inMap.put("parameter2", "|Lib"); 
inMap.put("parameter3", "P"); 

Map<String, Object> outMap = new LinkedHashMap<String, Object>(); 
outMap.put("output", 0); 
outMap.put("output1", ""); 

Map resultMap = genericDatabaseCaller.executeSimpleProcedure(procedureName, inMap, outMap); 

を我々はapplication-context.xml

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
</bean> 

<bean id="genericDatabaseCaller" 
    class="co.com.custom.GenericDatabaseCaller"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 
にいくつかの行を追加します。

注:データソースi私たちがEntityManagerをインスタンス化するのと同じものです。

私たちのクラスでは、@Respositoryという注釈を使用し、注釈をGenericDatabaseCallerフィールドに追加します。

@Repository(value = "customDao") 
public class JPACustomDao implements CustomDao { 

    /** entity manager. */ 
    private EntityManager em = null; 

    /** 
    * Sets the entity manager. 
    * 
    * @param entityManager {@link EntityManager}. 
    */ 
    @PersistenceContext 
    public void setEntityManager(EntityManager entityManager) { 
    this.em = entityManager; 
    } 

    @Autowired 
    private GenericDatabaseCaller genericStoredProcedure; 
} 

私はこれがうまくいきたいと思います。

+0

アーク:私はuが唯一の最初の解決策として述べたように、接続オブジェクトを取得することによって、問題を管理することができた方法をいくつか。私は他の解決策が私のためにも働くかどうかを調べるつもりです。ありがとう。 – Ran

1

hibernateセッションからの接続の取得に注意してください。現在のトランザクションの外部で2番目の接続を取得している可能性があります。

また、実装ではなくセッションインターフェイスを使用する方がよいでしょう。

@PersistenceContext 
private EntityManager em; 

@Transactional 
@Override 
public String create(final JpaPojo pojo) throws SQLException { 
    ReturningWork<Integer> work = new ReturningWork<Integer>() { 
     @Override 
     public String execute(Connection con) throws SQLException { 
      CallableStatement call = con.prepareCall("{?= call MyFunction(?,?,?)}"); 
      call.registerOutParameter(1, Types.INTEGER); 
      call.setString(2, pojo.getFooId()); 
      (...) 
      call.execute(); 
      return call.getString(1); 
     } 
    } 
    Session session = (Session) em.getDelegate(); 
    return session.doReturningWork(work); 
} 
+0

みんな、このコードはうまくいきます! –

関連する問題