使用javax.persistence.EntityManager注册存储过程输出参数
我正在使用EntityManager进行数据库操作。我想使用这个EntityManager执行存储过程。我正在使用下面的代码执行该过程,但不知道如何注册In/Out参数使用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.
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);
}