below is my hibernate code:
SessionFactory sessionFactory;
Session session = null;
LoginEntity user = null;
try {
sessionFactory = HibernateUtility.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
user = session.get(LoginEntity.class, user_id);
System.out.println(user.getUserCountryMapping()); // if I remove this line I get error..
session.getTransaction().commit();
return user;
} catch (Exception e) {
Logger.getLogger(BulkActionMethods.class.getName()).log(Level.SEVERE, null, e);
} finally {
if (session != null) {
session.close();
}
}
I am facing a weird issue with my code, When I remove the System.out.println(user.getUserCountryMapping()); line I am getting HTTP Status 500 - Internal Server Error error on browser but when I write this line I am getting expacted JSON response on browser..
Please someone help me to understand this issue.
Without seeing the error or your entity mappings, it's hard to give a firm answer.
However, cases like this are almost always due to uninitialized lazy collections. The line:
System.out.println(user.getUserCountryMapping());
makes Hibernate fetch the data in that relationship. If you don't do this within a Hibernate session, and then try to rely on this relationship later you will get a LazyInitializationException, if not handled it will be a HTTP status 500.
Replace
System.out.println(user.getUserCountryMapping());
with
Hibernate.initialize(user.getUserCountryMapping());
Read more about lazy vs eager fetch type.
Related
I'm trying to modify existing Java app (WildFly, Jboss, oracle) which currently working fine as using persistence-unit and EntityManager connect to Oracle database(using standalone.xml and persistence.xml). However, I need to create every time new connection to database for the user which calls new GET API Endpoint using credentials from the HttpHeaders. Currently, I'm creating new entitymanager object which session is commit, rollback nad close. Unfortunately time response for every call become higher and higher. There is warning about "PersistenceUnitUser" being already registered and memory usage constantly growing. So that is bad solution.
Is there any proper way to do it, which works witout any harms ?
P.S.
Currently app using standalone.xml and persistence.xml. And that is working fine. I'm calling java api endpoint using entity manager being connected as Admin user/pass but I need to create new connection using user/pass from the httpHeaders and call one sql statement to see proper results as ORACLE uses reserved word such us: 'user'. For instance : select * from table where create_usr = user. When done 'Main EntityManager will use data from it to continue some process.
Please see code example below :
#GET
#Path("/todo-list-enriched")
#Produces(MediaType.APPLICATION_JSON)
public Response getToDoListEnriched(#Context HttpHeaders httpHeaders, #QueryParam("skip") int elementNumber, #QueryParam("take") int pageSize, #QueryParam("orderby") String orderBy)
{
String userName = httpHeaders.getHeaderString(X_USER_NAME);
String userName = httpHeaders.getHeaderString(X_PASSWORD);
EntityManager entityManager = null;
try {
Map<String, String> persistenceMap = new HashMap<String, String>();
persistenceMap.put("hibernate.dialect","org.hibernate.dialect.Oracle8iDialect");
persistenceMap.put("hibernate.connection.username", asUserName);
persistenceMap.put("hibernate.connection.password", asPassword);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnitUser", persistenceMap);
entityManager = emf.createEntityManager();
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
-- Do some works as select, update, select
-- and after that
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().commit();
}
}
catch (Exception ex)
{
if (entityManager != null && entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
}
finally {
if (entityManager != null && entityManager.isOpen()) {
entityManager.close();
}
}
}
}
``
Best Regards
Marcin
You should define a connection pool and a datasource in the standalone.xml (cf. https://docs.wildfly.org/26.1/Admin_Guide.html#DataSource) and then use it in your persistence.xml and inject the EntitytManager in your rest service class (cf. https://docs.wildfly.org/26.1/Developer_Guide.html#entity-manager).
You may look at this example application: https://github.com/wildfly/quickstart/tree/main/todo-backend
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()
I got a deadlock problem with mysql and an application that I am developing. The application, based on spring boot, integration and jpa, has different threads and all of them can access this service:
#Override
#Transactional()
public List<TwitterUser> storeTwitterUsers(List<TwitterUser> twitterUsers)
{
logger.debug("Store list of users, total: " + twitterUsers.size());
List<TwitterUser> savedUsers = new ArrayList<>();
for ( TwitterUser twitterUser : twitterUsers ) {
TwitterUser user = getTwitterUserById(twitterUser.getTwitterId());
if ( user != null ) {
twitterUser.setId(user.getId());
user = entityManager.merge(twitterUser);
} else {
//HERE THE EXCEPTION IS THROWN
entityManager.persist(twitterUser);
user = twitterUser;
}
entityManager.flush();
savedUsers.add(user);
}
return savedUsers;
}
#Override
#Transactional(readOnly = true)
public TwitterUser getTwitterUserById(Long id)
{
Query query = entityManager.createQuery("from TwitterUser u where u.twitterId=:id");
query.setParameter("id", id);
TwitterUser twitterUser = null;
//Throw Exception NoResultException
try {
twitterUser = (TwitterUser)query.getSingleResult();
} catch (NoResultException e) {
//no result found
}
return twitterUser;
}
When more than one thread is within the method storeTwitterUsers, mysql throw this error:
Deadlock found when trying to get lock; try restarting transaction
This is the full stack track of the error:
http://pastebin.com/nZEvykux
I already read those two questions:
How to avoid mysql 'Deadlock found when trying to get lock; try restarting transaction'
Getting "Deadlock found when trying to get lock; try restarting transaction"
but my problem seems slightly different because I got the exception when almost any thread tries to persist the object.
Is there a clean and easy way to resolve the problem without implementing a low level code check? Can Spring JPA automatically manage the deadlock situation?
Any help is really appreciated, I am struggling with that error!
My question is about hibernate, actually I'm working on a Java EE application using hibernate and mysq.
Everything looks fine. but I still have one problem when I insert data via phpMyAdmin to my database, I cannot access them immediately via hibernate unless I started the server (tomcat) again.
This is because your transaction in phpMyAdmin was not committed.
Try running this query in phpMyAdmin before running commands.
SET ##AUTOCOMMIT = 1;
Or running commit; at the end of your query.
Possible duplicate of:
COMMIT not working in phpmyadmin (MySQL)
I noticed that i've forgot to add transaction.commit(); for every hibernate session.get(); method, so somehow it keeps data in the cache.
public List<User> getAllUsers(User user) throws Exception {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria c = session.createCriteria(User.class).add(Restrictions.ne("idUser", user.getIdUser()));
List<User> users = c.list();
tx.commit();//i forget to add this
return users;
} catch (Exception e) {
if (tx != null) tx.rollback(); throw e;
} finally {
session.close();
}
}
I am using jersey with mysql and hibernate 4 and c3p0. I have created a initialization servlet that configures hibernate and sets the current session context class to thread.
I have created hibernateUtils class that contains static methods for getting and committing sessions and I am using a filter to start a session on inbound request and commit it upon response.
The problem is that at some random intervals I am getting org.hibernate.TransactionException: nested transactions not supported exception, but I am not trying to create a new session except on the filter.
Correct me if I am wrong but when setting the current session class to thread I don't need to create a threadlocal in the hibernateutil, hibernate does this. So my question is, is this a safe way to handle that and what could cause the error happening on random intervals?
====================== EDIT ===========================
Sorry for not posting the code earlier.
So the filter implements the ContainerRequestFilter,ContainerResponseFilter
in the request filter I am doing
Session session = sessionfactory.getCurrentSession();
session.getTransaction().begin();
session.setDefaultReadOnly(readOnly);
and in the response
Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try {
if (transaction != null && !transaction.wasCommitted()
&& !transaction.wasRolledBack() && transaction.isActive()) {
transaction.commit();
}
} catch (HibernateException e) {
Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try {
if (transaction != null && transaction.isActive()) {
transaction.rollback();
}
} catch (HibernateException e) {
} finally {
Session session = sessionfactory.getCurrentSession();
try {
if (session != null && session.isOpen()) {
session.close();
}
} catch (HibernateException e) {
log.error("Closing session after rollback error: ", e);
throw e;
}
}
It seems that you are using programmatic transaction demarcation in your filter (as far as I understood). So please double check that you terminate properly each transaction, nevermind what append during the request (i.e. rollback if you get an exception and commit otherwise) :
try {
session.getTransaction().begin();
// call the filter chain
session.getTransaction().commit()
}
catch (RuntimeException e) {
session.getTransaction().rollback();
}
Without the code it's difficult to be sure, but I guess that for some request you didn't terminate the transaction properly (i.e. by a commit or by a rollback). So the transaction remains associated to the thread and the thread go back to the thread pool (in a very strange state since there is still a transaction associated with it), then another request reuse the same thread, a new transaction is created in the filter... and you got the exception.
EDIT
After looking carrefully at your code, it (may) confirms my assumptions.
Look at the flow when transaction.wasRolledBack()==true : it won't be commited nor rolled back.
And if you the javadoc for Transaction.wasRolledBack() :
Was this transaction rolled back or set to rollback only?
If the transaction is marked as "RollBack only" : it will return true, but it don't means that the transaction is ended. It means that the only possible ending state for the transaction is "RollBack".
But, on the other hand the same javadoc also say this:
Returns: boolean True if the transaction was rolled back via this local transaction; false otherwise.
I found that ambiguous.
So I suggest you to do this:
if (transaction != null && !transaction.wasCommitted()
&& !transaction.wasRolledBack() && transaction.isActive()) {
transaction.commit();
}else if(transaction.wasRolledBack()){
transaction.rollback();
}