使用javax.persistence.EntityManager注册存储过程输出参数

使用javax.persistence.EntityManager注册存储过程输出参数,java,persistence,ejb-3.0,Java,Persistence,Ejb 3.0,我正在使用EntityManager进行数据库操作。我想使用这个EntityManager执行存储过程。我正在使用下面的代码执行该过程,但不知道如何注册In/Out参数 Query query = appsEntityManager.createNativeQuery("{call test(?,?,?)}"); query.setParameter(1, ""); query.setParameter(2, ""); query.

我正在使用EntityManager进行数据库操作。我想使用这个EntityManager执行存储过程。我正在使用下面的代码执行该过程,但不知道如何注册In/Out参数

        Query query = appsEntityManager.createNativeQuery("{call test(?,?,?)}");
        query.setParameter(1, "");
        query.setParameter(2, "");
        query.setParameter(3, "");
        query.getResultList();
请帮忙解决这个问题。
没有办法解决这个问题吗?

尝试以下方法:

使用
实体管理器获取
java.sql.Connection

Connection cc = ((SessionImpl) em.getDelegate()).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);
}
另一个实现基于此。
创建扩展
StoredProcess
的类:

/**
 * 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);
    }
  }
}
注意数据源与实例化
EntityManager的数据源相同

然后在我们的课堂上,我们使用注释
@Respository
,并将
@Autowired
注释添加到
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;
}

我希望这对您有用。

请小心从hibernate会话中检索连接。您可能正在获取当前事务之外的第二个连接

此外,最好使用会话接口,而不是它的实现

@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);
}
@PersistenceContext
私人实体管理者;
@交易的
@凌驾
公共字符串创建(最终JpaPojo pojo)抛出SQLException{
ReturningWork=新的ReturningWork(){
@凌驾
公共字符串执行(连接con)引发SQLException{
CallableStatement call=con.prepareCall(“{?=callmyfunction(?,?)}”);
registerOutParameter(1,Types.INTEGER);
call.setString(2,pojo.getFooId());
(...)
call.execute();
return call.getString(1);
}
}
会话=(会话)em.getDelegate();
返回会话。doReturningWork(工作);
}

Arc:我是如何通过获取连接对象来管理问题的,正如你提到的,这只是第一个解决方案。我将尝试看看其他解决方案是否也适用于我。谢谢
@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;
}
@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);
}