EJB 3 with JDBC - jpa

Is it possible to use EJB 3 with JDBC. I read somewhere, that it's allowed.
However, I hear that EJB 3 implementation uses JTA, by default. What does that mean for JDBC? Is it only for the transaction support? That means JTA is used for transaction when using JDBC code? Meaning that even local transactions are implemented as global transactions?
Does it mean it's not a good idea to use JDBC with EJB 3? Many people point me to JPA, but it's an ORM. I want to use SQL.
any suggestions?

1º
That means JTA is used for transaction when using JDBC code ?
And
Meaning that even local transactions are implemented as global transactions ?
The EJB container CAN MAKE USE of resource manager local transactions AS AN OPTIMIZATION TECHNIQUE for enterprise beans for which distributed transactions ARE NOT NEEDED.
It is a good idea do the following when using a declarative or programmatic transaction demarcation:
declare resources using the Resource annotation in the enterprise bean class or using the resource-ref element in the enterprise bean’s deployment descriptor
Something like (setter method or member field)
// mappedName points to a global mapping name
#Resource(mappedName="java:/DefaultDS")
private javax.sql.DataSource ds;
And inside a business logic method
If you are using a declarative transaction
Connection conn = ds.getConnection();
If you are using a programmatic transaction
Declare a setter or member field UserTransaction
#Resource
private UserTransaction ut;
And
ut.beginTransaction();
Connection conn = ds.getConnection();
ut.commit();
Take care of the following
If you are using a Stateful session bean, do the following in the PrePassivate callback method
Close all JDBC connections in the PrePassivate method and assign the instance’s fields storing the connections to null
regards,

You can look at this page, it does appear that you can combine EJB3 with JDBC.
http://www.java2s.com/Tutorial/Java/0415__EJB3/UseJDBCInEJB.htm

If you are using JPA2, you can use entityManager.unwrap(Connection.class) to get actual connection and use with your JDBC code.
For example:
Connection connection = entityManager.unwrap( Connection.class );
try (Statement stmt = connection.createStatement()) {
stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
}
Does it mean it's not a good idea to use JDBC with EJB 3? Many people
point me to JPA, but it's an ORM. I want to use SQL.
Sometime it's necessary, for performance or compatibility issues. I usually use this technique to execute PL/PSQL with array parameters, complex Posgis SQL, etc.

Related

If a #Transactional annotated method is called from another #Transactional annotated method, does this result in two connections being consumed?

Off late, we have been getting hikari connection pools getting exhausted more than a couple of times. The exception being thrown is as follows:
"org.springframework.transaction.CannotCreateTransactionException:
Could not open JDBC Connection for transaction;
nested exception is java.sql.SQLTransientConnectionException:
HikariPool-1 - Connection is not available, request timed out after 30000ms."
What I have observed is that some unaware developers have added #Transactional annotation to a lot of simple get calls on the DB (Postgres).
We use JdbcTemplate to make DB calls with a default connection pool size of 10.
The public endpoints at the controllers are already annotated as #Transactional. Can adding the #Transactional annotation to the DAO Beans result in creation of nested connections when the service layer, which is a seperate bean, which calls the DAO layer is already #Transactional.
We also have a few scheduled CRON jobs, and I see that these are not exposed via a public api or exposed via a controller, but do I still need to add #Transactional to the parent level methods in such cron/internal methods to be able to optimally make db calls? We are not expecting changes to roll back for these cron jobs. We already use JdbcTemplate which uses Hikari Connection poo. Is #Transactional need at all in such cases to optimise performance.
All configurations are default spring boot configurations, so default Tx.Type is REQUIRED unless explicitly set.
#Transactional should be mainly use in service layer when you are about to use database connections, it should be used on minimum methods that represent a business flow.
I think you are over using it and may create unnecessary connections, thus create timeout on overloaded pool
Notice that you use only one database connection pool,as HikariCP, and not also PGBouncer for example.
Also see more performance/configuration tweaks for HikariCP in its wiki page

Is it OK to globally set the mybatis executor mode to BATCH?

I am currently developing a Spring Boot app, which uses mybatis for its persistence layer. I want to optimize the batch insertion of entities in the following scenario:
// flightSerieMapper and legMapper are used to create a series of flights.
// legMapper needs to use batch insertion.
#Transactional
public FlightSerie add(FlightSerie flightSerie) {
Integer flightSerieId = flightSeriesSequenceGenerator.getNext();
flightSerie.setFlightSerieId(flightSerieId);
flightSerieMapper.create(flightSerie);
// create legs in batch mode
for (Leg leg : flightSerie.getFlightLegs()) {
Integer flightLegId = flightLegsSequenceGenerator.getNext();
leg.setLegId(flightLegId);
legMapper.create(leg);
}
return flightSerie;
}
mybatis is configured as follows in application.properties:
# this can be externalized if necessary
mybatis.config-location=classpath:mybatis-config.xml
mybatis.executor-type=BATCH
This means that mybatis will execute all statements in batch mode by default, including single insert/update/delete statements. Is this OK? Are there any issues I should be aware of?
Another approach would be to use a dedicated SQLSession specifically for the LegMapper. Which approach is the best (dedicated SQLSession vs global setting in application.properties)?
Note: I have seen other examples where "batch inserts" are created using a <foreach/> loop directly in the mybatis xml mapper file. I don't want to use this approach because it does not actually provide a batch insert.
As #Ian Lim said, make sure you annotate mapper methods with inserts and updates with #Flush annotation if you globally set executor type to BATCH.
Another approach would be to use a dedicated SQLSession specifically
for the LegMapper. Which approach is the best (dedicated SQLSession vs
global setting in application.properties)?
Keep in mind that if you are using different SQL sessions for different mappers there will be different transactions for each SQL session. If a service or service method annotated with #Transactional uses several mappers that use different SQL sessions it will allocate different SQL transactions. So it's impossible to do atomic data operation that involves mappers with different SQL sessions.

Postgres Glassfish Pooling

Some tutorial says use org.postgresql.ds.PGConnectionPoolDataSource but some says just the org.postgresql.ds.PGSimpleDataSource... what is the difference between the two?
The difference is that the class org.postgresql.ds.PGConnectionPoolDataSource implements Connection Pooling, therefore it can provide some performance benefits.
According to the documentation:
Class PGSimpleDataSource
Simple DataSource which does not perform connection pooling. In order
to use the DataSource, you must set the property databaseName. The
settings for serverName, portNumber, user, and password are optional.
Note: these properties are declared in the superclass.
Class PGConnectionPoolDataSource
PostgreSQL implementation of ConnectionPoolDataSource. The app server
or middleware vendor should provide a DataSource implementation that
takes advantage of this ConnectionPoolDataSource. If not, you can use
the PostgreSQL implementation known as PoolingDataSource, but that
should only be used if your server or middleware vendor does not
provide their own. Why? The server may want to reuse the same
Connection across all EJBs requesting a Connection within the same
Transaction, or provide other similar advanced features.
See also:
Connection Pooling with PostgreSQL JDBC

eclipselink.read-only and transaction bounderies

I'm using EclipseLink as my JPA provider.
When I use the following code on a query object:
myQuery.setHint("eclipselink.read-only", "true");
The query is executed on a different connection than the original EntityManager is using and return wrong results.
Does it make sense that setting the query to read only will cause EclipseLink to run it on a different connection? (I'm using connection pooling).
In additional I've added in the persistence.xml:
<shared-cache-mode>NONE</shared-cache-mode>
to disable cross session cache.
Read-only queries are meant to only show read-committed data. If you want transactional data, you should not use read-only.
You may be able to use an exclusive connection, (persistence unit, or persistence context property)
"eclipselink.jdbc.exclusive-connection.mode"="Always"

JPA build entity manager with a specific JDBC connection instance

I want to manage the database connection outside entity manager context so that I can use it for different entity managers. The question is how can I build the entity manager factory or entity manager with my own connection instead of providing it with properties in persistence.xml?
In either case the answer is that you cannot, in SE you can specify the db connection properties when creating the EntityManagerFactory, but the db connection is still maintained by the EntityManager and for good reason, if you controlled this you could commit and rollback behind the EntityManager's back. If you gave the same db connection to multiple EntityManager's this would be chaos indeed, I am not sure why on earth you want to do this.
The best I can suggest is that you look into the EntityManager.getDelegate() (JPA 1.0) or EntityManager.unwrap(java.lang.Class cls) (JPA 2.0) methods they may return the underlying provider (ie. Hibernate) object which you may be able to pry the database connection out of, but you certainly won't be able to replace it.
In short really bad idea.