I am using Play Framework and currently doing a CRUD of users. I have created a repository for doing operations on the database using the Play Framework JPAApi. The relevant ones are this
<U> U jpaWrapper(Function<EntityManager, U> function) {
return jpaApi.withTransaction(function);
}
public CompletionStage<T> update(T entity) {
return supplyAsync(() -> jpaWrapper(em -> update(em, entity)), executionContext);
}
private T update(EntityManager em, T entity) {
em.refresh(entity);
return entity;
}
public CompletionStage<Usuario> findById(int id) {
return supplyAsync(
() -> jpaWrapper(em -> findById(id, em)),
executionContext);
}
private Usuario findById(int id, EntityManager em) {
return (Usuario) JpaResultHelper.getSingleResultOrNull(
em.createNamedQuery("Usuario.findById", Usuario.class)
.setParameter("id", id)
);
}
In my controller I am editing the user by first finding it on the repository and after that setting the correct parameters. This is the controller action.
public CompletionStage<Result> editUser() {
Usuario editedUser = formFactory.form(Usuario.class).bindFromRequest("id", "nombre", "email", "rol").get();
return usuarioRepository.findById(editedUser.getId()).thenCompose( dbUser -> {
dbUser.setNombre(editedUser.getNombre());
dbUser.setRol(editedUser.getRol());
dbUser.setEmail(editedUser.getEmail());
return usuarioRepository.update(dbUser).thenApplyAsync( u ->
redirect(routes.UserController.listUsers())
);
});
}
The problem is that when I call the method the entity appears to be not managed with the following stack trace.
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: java.lang.IllegalArgumentException: Entity not managed]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:251)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:178)
at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:382)
at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:380)
at scala.concurrent.Future.$anonfun$recoverWith$1(Future.scala:413)
at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:37)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:91)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
Caused by: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Entity not managed
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1592)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Entity not managed
at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1320)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1277)
at models.management.AbstractRepository.update(AbstractRepository.java:54)
at models.management.AbstractRepository.lambda$null$4(AbstractRepository.java:31)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:142)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:100)
at models.management.AbstractRepository.jpaWrapper(AbstractRepository.java:40)
at models.management.AbstractRepository.lambda$update$5(AbstractRepository.java:31)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
Related
I has develop API for integrate file in database in async task.
I want my entire file processed, and I record every error in the database.
My API call this Service
#Service
public class ImportFichier {
#Async("taskExecutor")
public void importReference(ImportFichierDTO importFichierDTO,
List<Reference> references,
Long idEntite,
Long currentUserId,
boolean update){
log.debug("Request to importReference pour entite : {}", idEntite);
for(Reference reference : references) {
if (update) {
referentielService.update(idEntite, reference, currentUserId, importFichierDTO.getId());
} else {
referentielService.add(idEntite, reference, currentUserId, importFichierDTO.getId());
}
}
// mise à jour de l'heure de fin du traitement d'import
importFichierDTO.setDateFin(ZonedDateTime.now());
importFichierService.save(importFichierDTO);
return;
}
For adding data, treatment call this service :
#Service
#Transactional
public class ReferentielCompteurServiceImpl implements ReferentielCompteurService {
....
#Override
#Transactional(noRollbackFor = {CustomException.class, ConstraintViolationException.class})
public Compteur add(Compteur compteur, Long entiteMereId, Long entiteId, Long userId, Long importId) {
Optional<ArticleEtat> articleEtat = articleEtatRepository.findOneByCode(compteur.getCodeEtat());
if (!articleEtat.isPresent()) {
if (importId > 0) {
importFichierTraceService.add(importId, compteur.getUuidReference().toString(), CustomError.ERROR_ARTICLE_ETAT_NOT_FOUND.getErrorDescription());
return compteur;
} else {
throw new CustomException(CustomError.ERROR_ARTICLE_ETAT_NOT_FOUND);
}
}
....
ReferentielCompteurDTO result = save(referentielCompteurDTO, importId);
And method "save" in the same service :
#Override
#Transactional(noRollbackFor = {CustomException.class, ConstraintViolationException.class})
public ReferentielCompteurDTO save(ReferentielCompteurDTO referentielCompteurDTO, Long importId) {
log.debug("Request to save ReferentielCompteur : {}", referentielCompteurDTO);
if (referentielCompteurDTO.getDateCreation() == null) {
referentielCompteurDTO.setDateCreation(ZonedDateTime.now());
}
referentielCompteurDTO.setDateModification(ZonedDateTime.now());
ReferentielCompteur referentielCompteur = referentielCompteurMapper.toEntity(referentielCompteurDTO);
try {
referentielCompteur = referentielCompteurRepository.save(referentielCompteur);
} catch (ConstraintViolationException cve) {
importFichierTraceService.add(importId, referentielCompteurDTO.getReferenceId().toString(), cve.getMessage());
}
return referentielCompteurMapper.toDto(referentielCompteur);
}
When I generate a ConstraintViolationException I have this exception :
Transaction was marked for rollback only; cannot commit' and exception = 'Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit'
org.springframework.orm.jpa.JpaSystemException: Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:312)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:540)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
I see several post, but I don't understand how solve this problem, and is it possible
Can you help me please?
Following the advice of M.Deinum, I try :
for importFichierTraceService.add
#Transactional(propagation = REQUIRES_NEW)
public void add(Long importId, String line, String message) {
I delete #Transactional and catch Exception
#Override
public ReferentielCompteurDTO save(ReferentielCompteurDTO referentielCompteurDTO, Long importId) {
And add catch Exception in :
#Override
public Compteur add(Compteur compteur, Long entiteMereId, Long entiteId, Long userId, Long importId) {
try {
result = save(referentielCompteurDTO, importId);
} catch (ConstraintViolationException cve) {
importFichierTraceService.add(importId, referentielCompteurDTO.getReferenceId().toString(), cve.getMessage());
return compteur;
}
Result is the same
I am working on a Spring-MVC appplication with Hibernate and PostgreSQL in which these days we are experiencing a very strange problem. Sometimes when an object is being persisted, I am returning it's ID from the DAO layer to the service layer. This ID is then being broadcasted via our PUSH framework, after which point the object is retrieved by a call. At this point I am getting a NPE, although the object is saved, primary-key ID is non-zero, session is also flushed before returning the ID. What might be going wrong?
Example :
#Override
public void addNestedGroupNoteComment(String commentText, int noteId, int commentId){
int saveId = this.groupNoteHistoryDAO.addGroupNoteComment(groupNoteHistory, noteId);
if(saveId!=0) {
notification.setCommentId(saveId);
this.chatService.sendNotification(notification, groupMembers.getMemberid());
}
DAO method :
#Repository
#Transactional
public class GroupNoteHistoryDAOImpl implements GroupNoteHistoryDAO {
private final SessionFactory sessionFactory;
#Autowired
public GroupNoteHistoryDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public int addGroupNoteComment(GroupNoteHistory noteHistory, int noteId) {
Session session = this.sessionFactory.getCurrentSession();
GroupNotes notes = (GroupNotes) session.get(GroupNotes.class, noteId);
if(notes!=null) {
notes.getGroupNoteHistorySet().add(noteHistory);
noteHistory.setMhistory(notes);
int saveId = (Integer) session.save(noteHistory);
session.flush();
return saveId;
}
}
}
Now, after broadcasting the ID, this method is called :
#Override
public GroupNoteHistory getGroupNoteHistoryById(int historyId) {
GroupNoteHistory groupNoteHistory = this.groupNoteHistoryDAO.getGroupNoteHistoryById(historyId);
// Above object is many times null, tried System.out, it was with non-zero values.
}
DAO method :
#Override
public GroupNoteHistory getGroupNoteHistoryById(int historyId) {
Session session = this.sessionFactory.getCurrentSession();
return (GroupNoteHistory) session.get(GroupNoteHistory.class, historyId);
}
Any thoughts?
Update
Error log :
HTTP Status 500 - Request processing failed; nested exception is java.lang.NullPointerException
type Exception report
message Request processing failed; nested exception is java.lang.NullPointerException
description The server encountered an internal error that prevented it from fulfilling this request.
exception
root cause
java.lang.NullPointerException
com.project_name.spring.service.GroupNoteHistoryServiceImpl.getGroupNoteHistoryById(GroupNoteHistoryServiceImpl.java:156)
sun.reflect.GeneratedMethodAccessor647.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
Here int saveId = this.groupNoteHistoryDAO.addGroupNoteComment(groupNoteHistory, noteId); you already have a GroupeNoteHistory.
After this you manipulate it and save it
noteHistory.setMhistory(notes);
int saveId = (Integer) session.save(noteHistory);
session.flush();
return saveId;`
So you must check if the GroupNoteHistory already exists and is not null before using it. That's why you get a NPE.
Finally this worked for me :
#Override
public int addGroupNoteComment(GroupNoteHistory noteHistory, int noteId) {
Session session = this.sessionFactory.openSession();
try {
session.beginTransaction();
GroupNotes notes = (GroupNotes) session.get(GroupNotes.class, noteId);
if(notes!=null) {
notes.getGroupNoteHistorySet().add(noteHistory);
noteHistory.setMhistory(notes);
session.save(noteHistory);
session.flush();
session.getTransaction().commit();
return noteHistory.getMhistoryid();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
session.close();
}
return 0;
}
I am getting run time error in Play Framework 2.5 (Java) :
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: java.lang.IllegalStateException: Tried to remove the Entit yManager, but none was set.]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:98)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
Caused by: java.util.concurrent.CompletionException: java.lang.IllegalStateException: Tried to remove the EntityManager, but none was set.
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593)
at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:21)
at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:18)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:63)
Caused by: java.lang.IllegalStateException: Tried to remove the EntityManager, but none was set.
at play.db.jpa.JPAEntityManagerContext.pop(JPAEntityManagerContext.java:74)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:155)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:195)
at play.db.jpa.TransactionalAction.call(TransactionalAction.java:25)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:108)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:56)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
Below is the code :
#Transactional
public Result logincheck(){
Form<User> loginForm = Form.form(User.class).bindFromRequest();
User user = loginForm.get();
User searchUser = UserDao.findUser(user);
if (searchUser != null){
return ok(homepage.render());
}
return ok(login.render(loginForm));
}
In class UserDao:
public static User findUser(User user){
EntityManager em = jpaApi.em();
TypedQuery<User> query = JPA.em().createQuery("select u.* from [RL].[dbo].[userdetails] u where u.userid = :username and u.password = :password", User.class);
query.setParameter("username", user.userid);
query.setParameter("password", user.password);
try{
return (User) query.getSingleResult();
} catch(NoResultException e){
return null;
}
}
We found this issue while working with play2.5. We fixed it by adding
the persistence.xml file into the project as specified here : Play 2.5 JavaJPA creating a persistence unit
and adding the following in the application.conf:
jpa.default=defaultPersistenceUnit
You are using JPA.em() and jpaApi in the same method. Actually this should be the same entity manager. Starting from play 2.5 the proper way is jpaApi, JPA.em() is deprecated. You should take care to inject jpaApi.
The code may be like this:
public static User findUser(User user) {
JPAApi jpaApi = Play.current().injector().instanceOf(JPAApi.class);
EntityManager em = jpaApi.em();
TypedQuery<User> query = em.createQuery("select u.* from [RL].[dbo].[userdetails] u where u.userid = :username and u.password = :password", User.class);
...
}
You can read more here about dependency injection in Play
I am using spring with hibernate and when I am trying to insert a data which already exists, it throws DataIntegrityViolationException.
So to handle this exception I have placed a try/catch block in my save method in DAO layer, but it's not getting caught.
After that I placed a try/catch block in save method of service layer also but there also its not getting caught.
I have a testMain method in my service layer and when I am handling there its getting caught there.
Please help how to handle this in my DAO layer
public class TestMain {
/**
* #param args
*/
public static void main(String[] args) {
ApplicationContext applicationContext = SpringUtil
.getApplicationContextInstance();
UserDaoService userDaoService = applicationContext.getBean("userDaoService",
UserDaoService.class);
UserDaoImpl userDao = applicationContext.getBean("userDaoImpl",
UserDaoImpl.class);
User user = new User();
user.setActive(true);
user.setEmail("shariquealam01#gmail.com");
user.setFirstName("Md");
user.setMiddleName("Sharique");
user.setLastName("Alam");
user.setId(1);
user.setPassword("123");
user.setUserName("shariquealam01");
userDaoService.saveUser(user);
}
}
#Service
public class UserDaoService {
#Autowired
public UserDao userDao;
#Transactional
public void saveUser(User user){
System.out.println("User Saving");
/*user.setActive(true);
user.setEmail("shariquealam06#gmail.com");
user.setFirstName("Md");
user.setMiddleName("Sharique");
user.setLastName("Alam");
user.setId(6);
user.setPassword("123");
user.setUserName("shariquealam06");*/
userDao.saveUser(user) ;
/*try{
System.out.println("Inside Service Try");
userDao.saveUser(user);
} catch (Exception e){
System.out.println("Exception Occured "+e);
}*/
// deleteUser(3);
}
}
#Repository
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public Role getRole(int id){
Session session = getSessionFactory().getCurrentSession();
Role role = (Role) session.get(Role.class, id);
return role;
}
#Override
public void saveUser(User user) {
// Session session = getSessionFactory().getCurrentSession();
/*role.setRoleId(102);
role.setRoleName("User");*/
// role.getUsers().add(user);
/*session.save(user);*/
//logger.info( "Executing Query to ADD User"); //Since this query is important for the state of application, have info logging
Role role = getRole(102);
user.getRoles().add(role);
Session session = sessionFactory.getCurrentSession();
session.save( user );
//userId = user.getId();
//logger.info( "User ADDED to DB with userId as {}", user.getId() );
//session.save(role);
}
}
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:163)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:730)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:592)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:515)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.sharique.service.UserDaoService$$EnhancerBySpringCGLIB$$956522ab.saveUser(<generated>)
at com.sharique.main.TestMain.main(TestMain.java:40)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
... 9 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Violation of PRIMARY KEY constraint 'PK__USER_DET__F3BEEBFF77DFC722'. Cannot insert duplicate key in object 'dbo.USER_DETAILS'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
... 22 more
The exception, as the stack trace should show, doesn't happen when you call persist() or save(). It happens when flush() is called, i.e. when the SQL insert statements are actually executed. And flush() is called automatically just before the transaction commits.
You could call flush() explicitely and catch the exception, but that would be useless, because Hibernate exceptions are irrecoverable. They leave the session in an unusable state. The only safe thing to do when facing such an exception is to rolback the transaction and close the session.
So do the right thing: use autogenerated primary keys and/or check that the data doesn't exist, using a query, before trying to insert it.
I have a working ORM and been able to map objects to my database. So its up an running.
I've created a web service that looks like this:
#Stateless
#Path("user")
#LocalBean
public class userFacade {
#PersistenceContext(unitName = "Fakebook3")
private EntityManager em;
public userFacade() {
// TODO Auto-generated constructor stub
}
public void persistUser(User user){
em.persist(user);
}
#GET
#Path("edit")
#Produces(MediaType.APPLICATION_JSON)
public Response editUserInformation(
#QueryParam("userid") int userid,
#QueryParam("jobbText") String jobbText,
#QueryParam("intresseText") String intresseText,
#QueryParam("bostadText") String bostadText
){
String jobbTextEscaped = StringEscapeUtils.escapeHtml3(jobbText);
String intresseTextEscaString = StringEscapeUtils.escapeHtml3(intresseText);
String bostadTextEscaped = StringEscapeUtils.escapeHtml3(bostadText);
String sql = "UPDATE user SET job=?, interest=?, bostad=? WHERE id="+userid;
Query query = em.createQuery(sql);
query.setParameter(1, jobbTextEscaped);
query.setParameter(2, intresseTextEscaString);
query.setParameter(3, bostadTextEscaped);
query.executeUpdate();
return Response.status(200).entity("This is a callback message. Handle it!").build();
}
}
I'm using eclipse web service tool and input the paramater values and get this error:
13:23:41,184 ERROR [org.jboss.as.ejb3.invocation] (default task-4) JBAS014134: EJB Invocation failed on component userFacade for method public javax.ws.rs.core.Response se.chas.fakebook.facade.userFacade.editUserInformation(int,java.lang.String,java.lang.String,java.lang.String): javax.ejb.EJBException: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: fakebook.user is not mapped [UPDATE fakebook.user SET user.job=?, user.interests=?, user.bostad=? WHERE id=1]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:190) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
and so on. I tried to create to map the entities using eclipse and placed them in the same folder as the entities.
But I'm still getting same exception. I also tried changing the sql statement from "... facebook.user ..." to only use "... user ..."
What am I doing wrong?
I can't upload images here so here comes a link with a project tree: http://imgur.com/4yemPZH
Your query should be like this:
String sql = "UPDATE User SET job=?, interest=?, bostad=? WHERE id="+userid;
Try this :
UPDATE user SET job=:job, interest=:interest, bostad=:bostad WHERE id="+userid
query.setParameter("job", jobbTextEscaped);
query.setParameter("interest", intresseTextEscaString);
query.setParameter("bostad ", bostadTextEscaped);