How to use Postresql Large Object API with Spring's JdbcTemplate - java

I need to access a Large Object using postgresql API. This is done like this:
PGConnection pgConn=(PGConnection)c
LargeObjectManager lobj =pgConn.getLargeObjectAPI();
LargeObject obj = lobj.open(imageOid, LargeObjectManager.READ);
InputStram is=obj.getInputStream();
I need to run this code from my DAO while using Spring's JdbcTemplate. How can I get access to the connection I'm using?

Assuming that DataSource has been configured correctly,
PGConnection pgConn = (PGConnection) jdbcTemplate.getDataSource().getConnection();

Related

Using DataSource with Transaction using Spring

I am working as part of a legacy j2ee application (plain application no Spring or Hibernate support)
The application exposes the following method:
public DataSource getConnectionDataSource();
DataSource is properly initiated to a specific DB schema by the product.
When I want to query the DB I create a jdbcTemplate object and query the like so:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("PRINT_LOCA",printerLocation);
DataSource printersSchemaDS = context.getCommonServices().getConnectionDataSource("printersSchema");
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(printersSchemaDS);
String printerId = jdbcTemplate.queryForObject("select printerId from printers where printer_location=:PRINT_LOCA ",parameters,String.class);
My question is how can I execute multiple Update SQL statements in a single transaction when I only have the DataSource object?
I see that there is TransactionTemplate in Spring, but is it possible to initialize it with DataSource object alone?
Thank you!
Try to take single connection from datasource, then use ordinary manual jdbc transaction:
try (Connection con = datasource.getConnection();) {
con.setAutoCommit(false);
// insert logic
con.commit();
} catch (SQLException e) {
// handle exception
con.rollback();
}
Full example here:
https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html

Unwrap NewProxyConnection and GetConnection from NewProxyConnection

I have the following structure:
A layer with Hibernate 4.0.1, using C3P0 as connection Pool.
I don't have datasources configured, I use a dynamic configuration of datasource like it:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persitenceUnit", createMap(ds));
'ds' is a object with my database properties, like user, password, url, ...
I get Entitymanager this way:
EntityManager em = emf.createEntityManager();
I try get connection this way:
EntityManagerImpl entityManagerImpl = (EntityManagerImpl)em;
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl)entityManagerImpl.getSession().getSessionFactory();
Connection con = sessionFactoryImpl.getConnectionProvider().getConnection();
But, con is a NewProxyConnection instance. I need execute a procedure that return an ORAData and con.prepareCall(sqlToProcedure) return a NewProxyCallableStatment that no have a getOraData, ie, this code don't work:
OracleCallableStatment ocs = (OracleCallableStatment)con.prepareCall('{call stp_test(?)}');
ocs.excute();
TestObjectodf to = ocs.getOraDATA(1, TestObject.getOraDataFactory());
The error happens in
OracleCallableStatment ocs = (OracleCallableStatment)con.prepareCall('{call stp_test(?)}');
I try:
NewProxyConnection npCon = sessionFactoryImpl.getConnectionProvider().getConnection();
Connection con = npCon.unwrap(Connection.class);
But don't work.
The unwrap() method will work, if you upgrade to the latest c3p0-0.9.5 prerelease version. unwrap() is a JDBC4 method, supported by c3p0 as of c3p0-0.9.5. Since you want an OracleCallableStatement, you will probably want to call the unwrap() method of a CallableStatement, rather than the unwrap() method of a Connection, as you try above.
Alternatively (and a bit more safely), with almost any version of the library, you can use c3p0's raw statement operations. See the docs.

How to get current Connection object in Spring JDBC

How can I get the current Connection object for an Oracle database? I'm using the JDBC module in Spring 3.0.5.
Obtain the Connection from the DataSource bean.
You can access the dataSource by using Spring dependency injection to inject it into your bean, or by accessing ApplicationContext statically:
DataSource ds = (DataSource)ApplicationContextProvider.getApplicationContext().getBean("dataSource");
Connection c = ds.getConnection();
Just an Info :
I am using Spring JDBC Template, which holds the current connection object for me, which can be received as follows.
Connection con;
con = getJdbcTemplate().getDataSource().getConnection();
Use DataSourceUtils.getConnection().
It returns connection associated with the current transaction, if any.
I'm not sure if this method was available when this question was originally posted, however, it seems the preferred way to do it in the latest version of Spring is with JdbcTemplate and PreparedStatementCreator. See https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html#query-org.springframework.jdbc.core.PreparedStatementCreator-org.springframework.jdbc.core.PreparedStatementSetter-org.springframework.jdbc.core.ResultSetExtractor- or any of the other query methods that take a PreparedStatementCreator as the first param:
jdbcTemplate.query(con -> {
// add required logic here
return con.prepareStatement("sql");
}, rs -> {
//process row
});
This has the advantage over the other provided answers (DataSourceUtils.getConnection() or jdbcTemplate.getDataSource().getConnection() as a new connection is not allocated, it uses the same connection management it would as calling any of the other jdbcTemplate querying methods. You also therefore do not need to worry about closing / releasing the connection, since spring will handle it.

using Spring JdbcTemplate

if i create a new instance of JdbcTemplate like so;
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource());
by passing the datasource as a param (the datasource retrieves a connection from server connection pool) am i required to close the connection when im finished with it?
In other words, if i have a pool of connections will the previous code cause my application to create a new connection each time a request executes the code
No. That's the whole deal. Use the JdbcTemplate and it will manage the ressources (Connection, PreparedStatement, ResultSet). It is an implementation of the template method design pattern.
Javadoc:
It simplifies the use of JDBC and helps to avoid common errors. It
executes core JDBC workflow, leaving
application code to provide SQL and
extract results.
What I did, was to extend the JdbcTemplate and override the execute method to use the connection pool (a particular case).

Spring DatasourceTransaction Manager Problem

final DataSource ds = DataSourceLocator.getInstance()
.getDataSource(sg.cmpl.starhub.lprs.Constants.APP_KEY);
final DataSourceTransactionManager txManager = new DataSourceTransactionManager();
txManager.setDataSource(ds);
final DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
final TransactionStatus status = txManager.getTransaction(def);
Connection conn = null;
PreparedStatement ps = null;
try {
/***************************************************************************/
conn = DataSourceUtils.getConnection(ds);
ps = conn.prepareStatement(sql);
ps.execute();
/***************************************************************************/
txManager.commit(status);
} catch (Exception e) {
txManager.rollback(status);
}
Is there something wrong with my transaction manager logic? It looks like unstable. When I insert new data, First time it seems to save and later I can't find the data in mysql database. Please help. Thanks a lot.
Assuming there's a special reason you want to do programmatic connection and transaction management I suggest taking a look at Spring's JdbcTemplate and wrap it's usage in a TransactionTemplate.
However as stated in the previous comment, you should try to avoid programmatic transaction management as much as possible and use annotations (#Transactional) or XML configuration (TransactionProxyFactoryBean or <tx:advice/>) instead.
Yes, there is something wrong. This is not the Spring way. You should not be putting commit/rollback logic in code like this. The advantage comes when you can do it declaratively, in configuration.
Have a look at the Spring transaction reference docs.
As a side note: according to Spring documentation if commit operation fails with TransactionException then rollback was already called and calling it again in catch block will trigger IllegalTransactionStateException.

Categories

Resources