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

Ran*_*Ran 1 java persistence ejb-3.0

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

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

请帮忙解决这个问题.有没有办法解决这个问题?

小智 6

试试这个实现:

获得java.sql.Connection使用你的EntityManager:

Connection cc = ((SessionImpl) em.getDelegate()).connection();
Run Code Online (Sandbox Code Playgroud)

通过这种方式,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);
}
Run Code Online (Sandbox Code Playgroud)

另一个实现基于这篇文章.
创建一个扩展的类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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用您的函数或存储过程:

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);
Run Code Online (Sandbox Code Playgroud)

为了实例化,GenericDatabaseCaller我们添加了一些行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>
Run Code Online (Sandbox Code Playgroud)

请注意,数据源与我们用于实例化的数据源相同EntityManager.

然后在我们的类中,我们使用注释@Respository并将注释添加 @AutowiredGenericDatabaseCaller字段中.

@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;
}
Run Code Online (Sandbox Code Playgroud)

我希望这适合你.