JPA and PostgreSQL - java

I'm on a project that uses the EclipseLink implementation of JPA to talk to a PostgreSQL database. I have a task for which PostgreSQL NOTIFY/LISTEN seems like a perfect fit. Unfortunately, I'm a JPA newb, and am struggling to figure out how to make it work. So I guess I really have two questions; answering either one will make me happy.
1) What's the best way for me to get a hold of the direct JDBC connection to the database? (Which I sincerely hope will prove to be of type org.postgresql.PGConnection.)
OR
2) What's the best way for me to emulate/access org.postgresql.PGConnection.getNotifications() via EclipseLink JPA?
Thank you very much for your help.
Edit: Two working solutions! I love this site. If anybody has anything to say about hidden gotchas/benefits that would make either Pascal's or Balus's solution better than the other before I hand out the checkmark, I'd like to hear it.

Getting a JDBC connection from an EntityManager in EclipseLink is answered in the EclipseLink wiki.
The way differs per JPA API version. Here's an extract from the wiki:
JPA 2.0
entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
...
entityManager.getTransaction().commit();
JPA 1.0
entityManager.getTransaction().begin();
UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)((JpaEntityManager)entityManager.getDelegate()).getActiveSession();
unitOfWork.beginEarlyTransaction();
java.sql.Connection connection = unitOfWork.getAccessor().getConnection();
...
entityManager.getTransaction().commit();

You should be able to get it from org.eclipse.persistence.internal.jpa.EntityManagerImpl that is returned by EntityManager.getDelegate():
java.sql.Connection conn = ((EntityManagerImpl)(em.getDelegate())).getServerSession().getAccessor().getConnection();

Related

Can you get metrics and statistics from Hibernate OGM?

I'm trying to get performance data from Hibernate OGM. It doesn't seem to have the Hibernate statistics classes like Hibernate ORM. Is there something equivalent?
The reason there are not specific classes is that you should be able to use the existing one in ORM.
For example:
org.hibernate.stat.Statistics statistics = getSessionFactory().getStatistics();
statistics.setStatisticsEnabled( true );
final Session session = openSession();
...
statistics.logSummary();
session.close();
If you think that something is missing or not working, you can signal it on the Hibernate OGM Jira or forum.
Davide

Is there a HQL version of Hibernate's Restrictions.sqlRestriction()?

I have a Java application using Hibernate 4.3.6. We use two different databases (one for regular deploy, other for unit/integration tests). There's a common db-function we'd like to use, but it's called different in each db dialect and Hibernate has no support for it. We've fixed this by simply creating subclasses for each Dialect and using:
this.registerFunction("normalizedFunctionName",
new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "arbitraryFunctionName(?1, ?2)"));
I can now use normalizedFunctionName(?, ?) in HQL. However I'd like to use it when using the Criteria API, something like:
sessionFactory.getCurrentSession()
.createCriteria(SomeClass.class)
.add(
Restrictions.lt("normalizedFunctionName(value, 'bla')", 3)
);
But this doesn't work. Now I've discovered there's:
Restrictions.sqlRestriction("arbitraryFunctionName(value, 'bla') < 3");
But since that's native SQL and not HQL, I can't use it.
So, my questions are:
Is there an HQL version of the Restrictions.sqlRestriction() feature?
Or is there another alternative to accomplish what I'm trying to do?

how to get query string from a javax.persistence.Query?

Maybe I am missing something, but I simply want to (in my java program) get the query string from a javax.persistence.Query object?
The Query object itself doesn't seem to have a method to do that. Also I know that our manager doesn't want us to use Spring framework stuff (for example using their QueryUtils class).
Is there not a way to simply get the query string from javax.persistence.Query object (Again, in a java program) ?!
no problem. hibernate:
query.unwrap(org.hibernate.Query.class).getQueryString()
or eclipselink
query.unwrap(JpaQuery.class).getDatabaseQuery().getJPQLString(); // doesn't work for CriteriaQuery
query.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString();
or open JPA
query.unwrap(org.apache.openjpa.persistence.QueryImpl.class).getQueryString()
...you get the idea....
There is no JPA-standard way, but some implementations have their own methods. For example DataNucleus JPA allows you to do
query.toString();
Look at the docs of your implementation for how they do it. See also this blog entry
http://antoniogoncalves.org/2012/05/24/how-to-get-the-jpqlsql-string-from-a-criteriaquery-in-jpa/
There is no standard way in JPA,
If you are using EclipseLink see,
http://wiki.eclipse.org/EclipseLink/FAQ/JPA#How_to_get_the_SQL_for_a_Query.3F
Edit your persistence properties file if JPA is provided by hibernate. Add the below section -
<property name="hibernate.show_sql" value="true"/>
Using OpenJPA I was able to do this:
OpenJPAQuery<MyEntity> q = (OpenJPAQuery<MyEntity>) query;
String mySQL = q.getQueryString();
The cast to OpenJPAQuery is important because the Query interface does not have the method getQueryString() on it.
The stored parameters are not filled in unfortunately but I'm working on figuring out how to do that myself.

Is there any lightweight JDBC wrapper with these features?

Named parameters, just like JdbcTemplate from Spring
XML configuration for JDBC connection settings
XML configuration for queries. Something like Hibernate <sql-query>. See Named SQL queries for an example
I'm thinking of trying to build my own, but I thought I'd ask here, maybe it's already been done.
Obviously I don't want to use neither an ORM nor JdbcTemplate.
What about MyBatis?
(source: mybatis.org)
I'am looking for the same thing, meanwhile try out DBUtils Utility:
http://commons.apache.org/dbutils/
Lightweight, open source and no dependencies.
Try JdbcSession from jcabi-jdbc. It's simple (as you want) and requires you to create a java.sql.DataSource before, for example (using BoneCP and H2 database):
BoneCPDataSource source = new BoneCPDataSource();
source.setDriverClass("org.h2.Driver");
source.setJdbcUrl("jdbc:h2:mem:x");
String name = new JdbcSession(source)
.sql("SELECT name FROM user WHERE id = ?")
.set(555)
.select(new SingleHandler<String>(String.class));

Force update in Hibernate

How can I force Hibernate to update an entity instance even if the entity is not dirty? I'm using Hibernate 3.3.2 GA, Hibernate Annotations and Hibernate EntityManager btw. I really want Hibernate to execute the generic UPDATE statement even if no property on the entity has changed.
I need this because some event listeners need to get invoked to do some additional work when the application runs for the first time.
Thanks!
ok - found it myself. This does the trick:
Session session = (Session)entityManager.getDelegate();
session.evict(entity);
session.update(entity);
For transients, you can check
if(session.contains(entity)) {
session.evict(entity);
}
session.update(entity);
session.evict(entity);
session.update(entity);
Good trick, but watch out for transient objects before putting this into some automation code. For transients I have then StaleStateObjectException
Try em.flush() which is used for EJB 3.0 entities, which also uses JPA similar to Hibernate 3.2.2 GA. If it doesn't work normally, use flush in transactions.

Categories