Get the url that the Connection uses to connect the database - java

I'm trying to get the url that the Connection uses to connect the database as following :
getEntityManager().unwrap(SessionImplementor.class).connection().getMetaData().getURL();
But I get this error :
java.lang.IllegalStateException: No transactional EntityManager available
How can I solve this ?
Edit:
I don't understand why this question was considered as duplicated to a Hibernate solution, I'm using JPA, so I'm trying to get the url using entityManager and not sessionFactory.

The solution was to add the #Transactional annotation.

The SessionImplementor Interface is form Hibernate, so which JPA Implementation are you using then?

Related

Spring Transaction (#Transaction) with Plain JDBC without JdbcTemplate

I have plain JDBC code which is doing transaction management using Connection Interface. I wanted to switch to Spring Transaction Management in small steps.
Firstly I want to provide PlatformTransactionManager for my datasource and annotate my class / methods with #Transaction and keep my other logic same ie. using connection / PreparedStatement etc.
All the examples, which I see use JdbcTemplate. I was wondering can Spring Transaction be used without JdbcTemplate?
Technically it is possible to use #Transactional without JdbcTemplate . But if you try to do it , you will sooner or later find that you are re-inventing what the things that are already done by JdbcTemplate.
What #Transactional does is that before executing a #Transactional method , it will help you to get a JDBC Connection from the DataSource , and start a transaction on this Connection .The JDBC Connection will then stored in a ThreadLocal.
That means if you do it without JdbcTemplate , you have to manually get this Connection from that ThreadLocal such that you can create a JDBC Statement from it for executing your SQL. Not to mention you have to manually release the JDBC resources such Statement , ResultSet etc. properly by yourself which all of these things are already take care by JdbcTemplate.
But if you have already implemented these JDBC codes manually and just want to let #Transactional to handle the transaction , you could try to inject the DataSource to your bean and then use the following method to get the Connection for your JDBC codes use :
Connection connection = DataSourceUtils.getConnection(dataSource);
Also checkout JdbcTemplate#execute(ConnectionCallback<T> action) , it is useful for migrating the existing JDBC codes that expects a JDBC Connection to work on to JdbcTemplate.
Yes it's possible. Adding a #Transactional annotation to your methods, as long as they follow the correct procedure should make your methods transactional. But as others have mentioned if you're in the process of updating your app you might as well ditch plain JDBC and move across to Spring JPA/JDBC (depending on which version of Spring you're using).

Avoiding "set session transaction read" in spring boot application with mysql

Thanks for looking at this. I have a tomcat spring boot application using JPA/Hibernate with mysql database back end. There are REST controllers exposed and various service methods are annotated with "#Transactional".
There are entity and repo objects used by JPA/Hibernate to persist and query data from the mysql database. The SQL queries are generated by JPA Hibernate entity and repo objects, like as follows:
public interface FooRepo extends JpaRepository < Foo, String > {
}
The above means that there is a table Foo which has a primary key of type String. There is also a separate class Foo.
While using the above FooRepo to query a single row in the table I see the following SQL queries
set session transaction read
select * from Foo where id='IdToQuery';
set session transaction read write
I understand the select SQL statement but not able to understand why "set session transaction read" is being executed?
Thanks,
ash
After Googling, the only suggestion that I found was to implement a separate read-only transaction connection pool.
From: http://256stuff.com/gray/docs/misc/performance_optimizing_spring_hibernate_transactions/

Does Hibernate query caching have any effect if it's used as a JPA provider only? [duplicate]

This question already has an answer here:
Will hibernate cache (EHCache for eg) will work with jpa specific code (if I use EntityManager/EM Factory instead of Session/SessionFactory)?
(1 answer)
Closed 5 years ago.
Hibernate offers to select different cache providers for query and L2 caching, but there seems to be no clear statement whether this has an effect if Hibernate is used as plain JPA provider only, i.e. by running queries with EntityManager instead of Session. All introductions simply speak of Hibernate which can mean Hibernate with Hibernate-specific features or Hibernate as JPA provider and then provide code examples involving Hibernate - to advertise the use or because it's a necessity?
In case that matters, I'm referring to a Java EE environment.
Use of the caching provider is only a matter of configuration of Hibernate. EntityManager is only thin wrapper around Session. FYI since Hibernate version 5.2 Session extends EntityManager, see https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Session.html .
So answer is - Hibernate uses all of their power even when used through JPA.
EDIT:
You can ensure that EntityManager is wrapper around Session by code like this:
EntityManager em = ...; // Get EntityManager from somewhere
Session session = em.unwrap(Session.class);
If you use Hibernate then you will successefully get session wrapped by EntityManager and can to use it directly.

Inject java.sql.Connection into controller for Ninja Framework

I want to use JOOQ to access my database from the Ninja Framework. How can I get a JDBC connection from a controller?
Here's resources I found that didn't quite work.
How to retrieve the datasource used by a persistence unit programmatically - Tedious set of steps to get the connection from an EntityManager.
http://blog.jooq.org/2015/05/26/type-safe-queries-for-jpas-native-query-api/ - works by building a query in JOOQ and passing to EntityManager.createNativeQuery. It's functional, but it's not as nice as just having the connection.
Could I inject the connection into a controller like so:
public Result myController(#DBConnection Connection connection) {
List<String> articles = DSL.using(connection).selectFrom(ARTICLE).fetch(ARTICLE.TITLE);
return Results.html().render("template", articles);
}
DropWizards has a plugin that looks like a winner: https://github.com/benjamin-bader/droptools/tree/master/dropwizard-jooq
public BlogPost getPost(#QueryParam("id") int postId, #Context DSLContext database) {
BlogPostRecord post = database
.selectFrom(POST)
.where(POST.ID.equal(postId))
.fetchOne();
// do stuff
}
Following up on #LukasEder's answer this is the approach:
HibernateEntityManagerFactory hibernateEntityManagerFactory = ((EntityManagerImpl) entityManager).getFactory();
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory();
C3P0ConnectionProvider c3P0ConnectionProvider = (C3P0ConnectionProvider) sessionFactoryImpl.getConnectionProvider();
Connection connection = c3P0ConnectionProvider.getConnection();
This is obviously very very strange and bad code.
A clean solution is to provide access to Connection / DataSource by Ninja directly (separating the connection pool from Hibernate or any implementation). That is not too hard and is partly done in the ebeans plugin. Let's discuss that on our mailing list if you are interested in contributing code :)
Short of any option to retrieve a JDBC Connection or DataSource from ninja framework directly, the standard approach should be to "unwrap" it from the EntityManager:
Connection connection = em.unwrap(Connection.class);
See also: How to get DataSource or Connection from JPA2 EntityManager in Java EE 6
A Hibernate-specific approach is documented here: How to retrieve the datasource used by a persistence unit programmatically

No session currently bound to execution context

I got below exception when I used session.getCurrentSession().
I have mentioned
hibernate.current_session_context_class: managed
org.hibernate.HibernateException: No session currently bound to execution context
at org.hibernate.context.internal.ManagedSessionContext.currentSession(ManagedSessionContext.java:75)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at io.dropwizard.hibernate.AbstractDAO.currentSession(AbstractDAO.java:36)
at io.dropwizard.hibernate.AbstractDAO.persist(AbstractDAO.java:149)
I use this with dropwizard. Can anyone help me to solve this?
If you are using Dropwizard Hibernate. You need to add #UnitOfWork annotation to your Resource method. More info within dropwizard manual, hibernate chapter.
Can you try with : session.openSession() - It tell hibernate to always opens a new session and you have to close once you are done with the operations. With session.getCurrentSession(), hibernate returns a session bound to a context that you don't need to close and only need to set the hibernate.current_session_context_class to thread.
You can also configure session with SpringSessionContext, if your application is Spring based.
Edit your hibernate-cfg.xml with below line:
hibernate.current_session_context_class=org.springframework.orm.hibernate3.SpringSessionContext
What above line will do?
Making session context class as "org.springframework.orm.hibernate3.SpringSessionContext
", Hibernate will assume it is executing inside of a Spring transactional context (i.e. through a Spring transactional aspect) and Spring will now manage your transaction for you. However if you call getCurrentSession() outside of such a context, Hibernate will throw an exception complaining that no Session is bound to the thread.

Categories