I am using EntityManager for database operations. I want to execute stored procedure using this EntityManager. I am using below code to execute the procedure but don't know how to register for In/Out parameters .
Query query = appsEntityManager.createNativeQuery("{call test(?,?,?)}");
query.setParameter(1, "");
query.setParameter(2, "");
query.setParameter(3, "");
query.getResultList();
Please help to solve this. Is theren't any way to achieve this problem?
Try this implementations:
Obtain a java.sql.Connection
using your EntityManager
:
Connection cc = ((SessionImpl) em.getDelegate()).connection();
With this Connection
you can use the java.sql.CallableStatement
class to make calls to stored procedures and functions, by this way:
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);
}
Another implementation is based on this post .
Create a class that extends 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);
}
}
}
Then, you can invoke your function or stored procedure:
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);
To instantiate GenericDatabaseCaller
we add some lines to our 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>
Note that the data source is the same that we use to instantiate the EntityManager
.
Then in our class we use the annotation @Respository
and add the @Autowired
annotation to the GenericDatabaseCaller
field.
@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;
}
I hope this works for you.
Carefull with the retrieval of connection from the hibernate session. One might be getting a second connection outside of the current transaction.
Also it is better to use the Session inteface instead of its implementation.
@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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.