Googled a lot but didn't get any proper solution. I am trying to make a simple e-commerce website where I have to show a list of orders in admin panel but got stuck there. Error says 'Session is closed!' but I have opened a session at the begging of method. Please someone tell me what I am doing wrong.
public List<OrderModel> getAllOrders() throws HibernateException {
session = sessionFactory.openSession();
try {
final String hql = "FROM OrderModel WHERE status=:status";
Query query = session.createQuery(hql);
query.setParameter("status", "0");
return query.list();
} catch (HibernateException e) {
throw new HibernateException(e.getMessage());
} finally {
if(session.isOpen()){
session.close();
}
}
}
Session is declared in parent class.
#Autowired
protected SessionFactory sessionFactory;
protected Session session;
protected Transaction trans;
Try to replace this if(session.isOpen()) with if(session == null || session.isOpen() == false)
Copying from the comment:-
Your session object is a class variable, which is not thread safe. Perhaps some other thread is closing the session? Try putting session inside the method like
Session session = sessionFactory.openSession();
Also have a look at DAO pattern.
i have an application Java + Jersey + Hibernate. Have too an .ini file, i want to get this access url to database when i start the server. I tried one option, but it makes persistence.xml alter every requisition and turns all of them extremely slow. The slow solution is:
public static EntityManager getEntityManager() {
String url = "jdbc:firebirdsql:xxx.xxx.xx.xxx/3040:c:\\database\\database.FDB";
EntityManager em = null;
Map properties = new HashMap();
properties.put("hibernate.connection.url", url);
try {
emf = Persistence.createEntityManagerFactory("aplication", properties);
} catch (Exception e) {
e.printStackTrace();
}
return em = (EntityManager) emf.createEntityManager();
}
Is there another way to alter persistence.xml url to database one time and no more? I need a performer solution, dont want very slow solutions.
NOTE: The motive i need this is because i have a configuration application in phyton who alters the ini file for each new customer. My application in Java reads this ini file.
You have to create the EntityManagerFactory a single time and cache it.
Here you create it at each time you create an EntityManager instance.
You could create the EntityManagerFactory in a listener or hook method that is invoked as your application is started and fully initialized :
private static EntityManagerFactory emf; // share emf
public void init() {
String url = "jdbc:firebirdsql:xxx.xxx.xx.xxx/3040:c:\\database\\database.FDB";
Map properties = new HashMap();
properties.put("hibernate.connection.url", url);
try {
emf = Persistence.createEntityManagerFactory("aplication", properties);
} catch (Exception e) {
e.printStackTrace();
}
}
Then use the cached EntityManagerFactory in getEntityManager() :
public static EntityManager getEntityManager() {
return (EntityManager) emf.createEntityManager();
}
I am using:
Web App (a filter opens session. DAO uses getCurrentSession())
Hibernate
Spring (AOP configuration over Service)
xml configuration for all
DTO between Mbean and Service
Well, I have two methods (business service):
service.findUser(..DTO..)
service.updateUser(..DTO..)
update throws org.hibernate.NonUniqueObjectException exception.
How can I avoid that?
I need to use update, not merge.
Thanks in advance.
//MBean.java method
public void testUpdateUser(ActionEvent e) {
System.out.println(name);
ServiceResponse<UserDto> serviceResponse = super.getPrincipalService().findUser(name);
UserDto userDto = serviceResponse.getResponseList().get(0);
//update some properties here
serviceResponse = super.getPrincipalService().updateUser(userDto);
LOG.info("" + serviceResponse);
}
//Service.java: update method
public ServiceResponse<UserDto> updateUser(UserDto userDto) {
LOG.info("");
ServiceResponse<UserDto> serviceResponse = new ServiceResponse<UserDto>();
try {
User user = this.getGlobalMapper().map(userDto, User.class);
//
this.getUserDao().update(user);
userDto = this.getGlobalMapper().map(user, UserDto.class);
serviceResponse.getResponseList().add(userDto);
serviceResponse.setOperationCodeResponse(ServiceResponseCode.OK);
serviceResponse.getMessages().add("Operacion OK");
} catch (Exception e) {
serviceResponse.getMessages().add(e.getMessage());
serviceResponse.setOperationCodeResponse(ServiceResponseCode.MODEL_ERROR);
LOG.error("", e);
}
return serviceResponse;
}
//Exception result
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.softlogia.copi.model.domain.User#155]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:696)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:296)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:241)
at org.hibernate.event.internal.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireUpdate(SessionImpl.java:705)
at org.hibernate.internal.SessionImpl.update(SessionImpl.java:697)
at org.hibernate.internal.SessionImpl.update(SessionImpl.java:693)
I am assuming you are using pure Hibernate as ORM; simply put, regardless of the status of your db, you have in your current Hibernate session different copies of the same row. To resolve this you can:
1) flush() the hibernate session after every writing operation on db (insert or update)
OR
2) In your update metod call merge() instead of saveOrUpdate()
Method Hibernate.createBlob() is deprecated from Hibernate 4.0.1 and moved to Hibernate.getLobCreator(Session session).createBlob(). Any solution what should I pass inside method getLobCreator(Session session), i.e in place of Session, Or any other solution showing how to retrieve and save an image into DB using Spring and Hibernate.
According to this easy tutorial,
Session Object
A Session is used to get a physical connection with a database. The Session object is lightweight and designed to be
instantiated each time an interaction is needed with the database.
Persistent objects are saved and retrieved through a Session object.
The session objects should not be kept open for a long time because
they are not usually thread safe and they should be created and
destroyed them as needed.
In Hibernate 4.0+ you can get Session object from a SessionFactory. Let's write a handy class for this task.
package your.company.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration().configure();
ServiceRegistry registry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(registry);
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}
Then:
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
byte[] bFile = /* load image into byte array */;
Blob image = Hibernate.getLobCreator(session).createBlob(bFile);
/* ? Your actions with Blob ? */
session.getTransaction().commit();
Let me know, if it works.
Or (assume Employee is a POJO with a field #Lob private byte[] photo;, binded to the corresponding table):
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
byte[] bFile = /* load image into byte array */;
Employee employee = new Employee();
employee.setPhoto(bFile);
session.save(employee);
session.getTransaction().commit();
Info from mkyong.com. Here you can find the full example of how to save image into database. And the example of how to retrieve image.
Note: For Hibernate 4.3+ your code inside try block slightly changes. Because class ServiceRegistryBuilder is replaced by StandardServiceRegistryBuilder.
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties());
SessionFactory factory = configuration.buildSessionFactory(builder.build());
We have a JPA application (using hibernate) and we need to pass a call to a legacy reporting tool that needs a JDBC database connection as a parameter. Is there a simple way to get access to the JDBC connection hibernate has setup?
As per the hibernate docs here,
Connection connection()
Deprecated. (scheduled for removal in 4.x). Replacement depends on need; for doing direct JDBC stuff use
doWork(org.hibernate.jdbc.Work) ...
Use Hibernate Work API instead:
Session session = entityManager.unwrap(Session.class);
session.doWork(new Work() {
#Override
public void execute(Connection connection) throws SQLException {
// do whatever you need to do with the connection
}
});
Where you want to get that connection is unclear. One possibility would be to get it from the underlying Hibernate Session used by the EntityManager. With JPA 1.0, you'll have to do something like this:
Session session = (Session)em.getDelegate();
Connection conn = session.connection();
Note that the getDelegate() is not portable, the result of this method is implementation specific: the above code works in JBoss, for GlassFish you'd have to adapt it - have a look at Be careful while using EntityManager.getDelegate().
In JPA 2.0, things are a bit better and you can do the following:
Connection conn = em.unwrap(Session.class).connection();
If you are running inside a container, you could also perform a lookup on the configured DataSource.
If you are using JAVA EE 5.0, the best way to do this is to use the #Resource annotation to inject the datasource in an attribute of a class (for instance an EJB) to hold the datasource resource (for instance an Oracle datasource) for the legacy reporting tool, this way:
#Resource(mappedName="jdbc:/OracleDefaultDS") DataSource datasource;
Later you can obtain the connection, and pass it to the legacy reporting tool in this way:
Connection conn = dataSource.getConnection();
if you use EclipseLink:
You should be in a JPA transaction to access the Connection
entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
...
entityManager.getTransaction().commit();
Hibernate 4 / 5:
Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> doSomeStuffWith(connection));
Since the code suggested by #Pascal is deprecated as mentioned by #Jacob, I found this another way that works for me.
import org.hibernate.classic.Session;
import org.hibernate.connection.ConnectionProvider;
import org.hibernate.engine.SessionFactoryImplementor;
Session session = (Session) em.getDelegate();
SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider cp = sfi.getConnectionProvider();
Connection connection = cp.getConnection();
The word pure doesn't match to the word hibernate.
EclipseLink
Getting a JDBC Connection from an EntityManager
It's somewhat straightforward as described in above link.
Note that the EntityManager must be joined to a Transaction or the unwrap method will return null. (Not a good move at all.)
I'm not sure the responsibility of closing the connection.
// --------------------------------------------------------- EclipseLink
try {
final Connection connection = manager.unwrap(Connection.class);
if (connection != null) { // manage is not in any transaction
return function.apply(connection);
}
} catch (final PersistenceException pe) {
logger.log(FINE, pe, () -> "failed to unwrap as a connection");
}
Hibernate
It should be, basically, done with following codes.
// using vendor specific APIs
final Session session = (Session) manager.unwrap(Session.class);
//return session.doReturningWork<R>(function::apply);
return session.doReturningWork(new ReturningWork<R>() {
#Override public R execute(final Connection connection) {
return function.apply(connection);
}
});
Well, we (at least I) might don't want any vendor-specific dependencies. Proxy comes in rescue.
try {
// See? You shouldn't fire me, ass hole!!!
final Class<?> sessionClass
= Class.forName("org.hibernate.Session");
final Object session = manager.unwrap(sessionClass);
final Class<?> returningWorkClass
= Class.forName("org.hibernate.jdbc.ReturningWork");
final Method executeMethod
= returningWorkClass.getMethod("execute", Connection.class);
final Object workProxy = Proxy.newProxyInstance(
lookup().lookupClass().getClassLoader(),
new Class[]{returningWorkClass},
(proxy, method, args) -> {
if (method.equals(executeMethod)) {
final Connection connection = (Connection) args[0];
return function.apply(connection);
}
return null;
});
final Method doReturningWorkMethod = sessionClass.getMethod(
"doReturningWork", returningWorkClass);
return (R) doReturningWorkMethod.invoke(session, workProxy);
} catch (final ReflectiveOperationException roe) {
logger.log(Level.FINE, roe, () -> "failed to work with hibernate");
}
OpenJPA
Runtime Access to DataSource
OPENJPA-1803 Unwrap EntityManager to Connection
I'm not sure OpenJPA already serves a way using unwrap(Connection.class) but can be done with the way described in one of above links.
It's not clear the responsibility of closing the connection. The document (one of above links) seems saying clearly but I'm not good at English.
try {
final Class<?> k = Class.forName(
"org.apache.openjpa.persistence.OpenJPAEntityManager");
if (k.isInstance(manager)) {
final Method m = k.getMethod("getConnection");
try {
try (Connection c = (Connection) m.invoke(manager)) {
return function.apply(c);
}
} catch (final SQLException sqle) {
logger.log(FINE, sqle, () -> "failed to work with openjpa");
}
}
} catch (final ReflectiveOperationException roe) {
logger.log(Level.FINE, roe, () -> "failed to work with openjpa");
}
Hibernate uses a ConnectionProvider internally to obtain connections. From the hibernate javadoc:
The ConnectionProvider interface is not intended to be exposed to the application. Instead it is used internally by Hibernate to obtain connections.
The more elegant way of solving this would be to create a database connection pool yourself and hand connections to hibernate and your legacy tool from there.
I ran into this problem today and this was the trick I did, which worked for me:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("DAOMANAGER");
EntityManagerem = emf.createEntityManager();
org.hibernate.Session session = ((EntityManagerImpl) em).getSession();
java.sql.Connection connectionObj = session.connection();
Though not the best way but does the job.
Below is the code that worked for me. We use jpa 1.0, Apache openjpa implementation.
import java.sql.Connection;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAPersistence;
public final class MsSqlDaoFactory {
public static final Connection getConnection(final EntityManager entityManager) {
OpenJPAEntityManager openJPAEntityManager = OpenJPAPersistence.cast(entityManager);
Connection connection = (Connection) openJPAEntityManager.getConnection();
return connection;
}
}
I'm using a old version of Hibernate (3.3.0) with a newest version of OpenEJB (4.6.0). My solution was:
EntityManagerImpl entityManager = (EntityManagerImpl)em.getDelegate();
Session session = entityManager.getSession();
Connection connection = session.connection();
Statement statement = null;
try {
statement = connection.createStatement();
statement.execute(sql);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}
I had an error after that:
Commit can not be set while enrolled in a transaction
Because this code above was inside a EJB Controller (you can't commit inside a transaction). I annotated the method with #TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED) and the problem was gone.
Here is a code snippet that works with Hibernate 4 based on Dominik's answer
Connection getConnection() {
Session session = entityManager.unwrap(Session.class);
MyWork myWork = new MyWork();
session.doWork(myWork);
return myWork.getConnection();
}
private static class MyWork implements Work {
Connection conn;
#Override
public void execute(Connection arg0) throws SQLException {
this.conn = arg0;
}
Connection getConnection() {
return conn;
}
}
I am a little bit new to Spring Boot, I have needing the Connection object to send it to Jasperreport also, after trying the different answers in this post, this was only useful for me and, I hope it helps someone who is stuck at this point.
#Repository
public class GenericRepository {
private final EntityManager entityManager;
#Autowired
public GenericRepository(EntityManager entityManager, DataSource dataSource) {
this.entityManager = entityManager;
}
public Connection getConnection() throws SQLException {
Map<String, Object> properties = entityManager.getEntityManagerFactory().getProperties();
HikariDataSource dataSource = (HikariDataSource) properties.get("javax.persistence.nonJtaDataSource");
return dataSource.getConnection();
}
}