2012-02-23 3 views
2

Не могли бы вы сообщить, что здесь неправильно. Так мой метод в классе контроллера выглядит так:Play framework on tomcat + lighttpd - jpa

public static void save(Long jobId, Long posetByUserId) throws Exception 
{ 
    try{ 
     java.util.Date date = new java.util.Date(); 
     SavedJob job = SavedJob.findByUserIdJobId(connectedUserID(), jobId); //place 1 
     String validationText = null; 

     if(job != null){   //place 2 
      validationText = play.i18n.Messages.get("saved.already"); 
      renderJSON(validationText); 
     }else{ 

      SavedJob saveJob = new SavedJob(); 
      saveJob.userID = connectedUserID(); 
      saveJob.jobId = jobId; 
      saveJob.insertDate = date; 
      saveJob.updateDate = date; 
      saveJob.posetByUserId = posetByUserId; 
      saveJob.message = play.i18n.Messages.get("save.saved"); 

      UserProfile userProfile = connectedUser(); 
      userProfile.arlSavedJobs.add(saveJob); 
      UserProfile.saveUser(userProfile); 
        ..... 
      } 
....... 
} 

Я вызываю вышеуказанный метод, используя AJAX.

Дело 1 Когда я запускаю игру в режиме разработки (не tomcat) и указываю пул потоков, как 1, все работает хорошо.

Дело 2 Я развернул это для tomcat + lighttpd. Вышеуказанный метод выходит из строя.

Если я вызываю вышеуказанный метод дважды, кажется, что первый запрос находится в «месте 1» выше в среднем времени, второй запрос достиг «места 2» и выдает сообщение об ошибке «saved.already». Запрос не сериализуется.

Уверен, что я делаю что-то не так, но вы можете посоветовать. Мне нужны оба запроса для сохранения двух элементов.

Спасибо за помощь.

Я все еще пытаюсь отлаживать дальше. Извиняюсь, если я ошибаюсь, похоже, проблема сводится к спячке, пытаясь сделать вставку вместо обновления.

org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 

hibernate tries to fire an insert for an already saved entiry instead of an update 

Для примера 2 ниже: Я посылаю 2 заявки. Запрос 1 сохраняется и теперь у меня есть один объект в userProfile.arlSavedJobs.add (saveJob); Запрос 2 приходит так, что это должно привести к 1 вставке и 1 обновлению, но я вижу, что hibernate пытается запустить две вставки и дает уникальное исключение ограничения. Есть идеи?

Обратите внимание: UserProfile.saveUser (userProfile); выполняет слияние с userprofile. После слияния он вызывает вставку вместо обновления для уже сохраненной сущности.?


Удовлетворительно оценено. После расследования это где я нахожусь: Когда приходит первый запрос, он добавляет объект в список в этом месте: userProfile.arlSavedJobs.add (saveJob); Сохранение отлично работает. Когда второй запрос приходит, этот список «arlSavedJobs» уже имеет объект, а второй запрос добавляет еще один объект в тот же список. Когда он достигает inle "UserProfile.saveUser (userProfile);" и пытается сохранить его, он должен запустить 1 вставку для нового объекта и 1 обновление для уже существующего объекта (добавлено по запросу 1). Однако он вызывает 2 вставки для обоих объектов и дает уникальное исключение ограничения. Траектория стека выглядит следующим образом:

[2012-02-23 23: 37: 39,914] DEBUG 21530 [http-8080-3] - org.hibernate.jdbc.util.SQLStatementLogger.logStatement (SQLStatementLogger.java:111) - вставить в SAVED_JOB (DELETE_FLAG, INSERT_DATE, POSTED_BY_USER_ID, UPDATE_DATE, JOB_ID, USER_ID) значения (?,?,?,?,?,?) [2012-02-23 23: 37: 39,967] DEBUG 21583 [http- 8080-3] - org.hibernate.jdbc.util.SQLStatementLogger.logStatement (SQLStatementLogger.java:111) - вставить в SAVED_JOB (DELETE_FLAG, INSERT_DATE, POSTED_BY_USER_ID, UPDATE_DATE, JOB_ID, USER_ID) значения (?,?,?,?, ?,?) [2012-02-23 23: 37: 40,019] ОШИБКА 21635 [http-8080-3] - org.hibernate.util.JDBCExceptionReporter.logExceptions (JDBCExceptionReporter.java:234) - Дублируемая запись «4-1 'для ключа' PRIMARY ' [2012-02-23 23: 37: 40,075] ОШИБКА 21691 [http-8 080-3] - org.hibernate.event.def.AbstractFlushingEventListener.performExecutions (AbstractFlushingEventListener.java:348) - Не удалось синхронизировать состояние базы данных с сеансом org.hibernate.exception.ConstraintViolationException: Не удалось выполнить JDBC пакетное обновление в org.hibernate.exception.SQLStateConverter.convert (SQLStateConverter.java:96) в org.hibernate.exception.JDBCExceptionHelper.convert (JDBCExceptionHelper.java:66) в org.hibernate. jdbc.AbstractBatcher.executeBatch. (0). org.hibernate.event.def.AbstractFlushingEventListener.performExecutions (AbstractFlushingEventListener.java:345) at org.hibernate.event.def.DefaultFlushEventListener.onFlush (DefaultFlushEventListener.java:51) at org.hibernate.impl.SessionImpl.flush (SessionImpl.java:1216) at org.hibernate.ejb.AbstractEntityManagerImpl.flush (AbstractEntityManagerImpl.java:795) at play.db.jpa.JPABase._save (JPABase.java:47) at play.db.jpa.GenericModel.save (GenericModel. Java: 184) на models.UserProfile.saveUser (UserProfile.java:401) на controllers.JTLeadsController.saveLead (JTLeadsController.java:202) на sun.reflect.NativeMethodAccessorImpl.invoke0 (нативный метод) в sun.reflect .NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) на sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) на java.lang.reflect.Method.invoke (Method.java:597) в play.mvc .ActionInvoker.invokeWithContinuation (ActionInvoker .java: 546) в play.mvc.ActionInvoker.invoke (ActionInvoker.java:500) в play.mvc.ActionInvoker.invokeControllerMethod (ActionInvoker.java:476) в play.mvc.ActionInvoker.invokeControllerMethod (ActionInvoker.java : 471) at play.mvc.ActionInvoker.invoke (ActionInvoker.java:159) at play.server.ServletWrapper $ ServletInvocation.execute (ServletWrapper.java:540) at play.Invoker $ Invocation.run (Invoker.java : 265) на play.server.ServletWrapper $ ServletInvocation.run (ServletWrapper.java:531) на play.Invoker.invokeInThread (Invoker.java:67) на play.server.ServletWrapper.service (ServletWrapper.java:130) at javax.servlet.http.HttpServlet.service (HttpServlet.java:717) на org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:290) в org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:206) на org.apache.catalina.core. StandardWrapperValve.invoke (StandardWrapperValve.java:233) на org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:191) на org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:127) на org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:102) в org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:109) на org.apache.catalina.connector. CoyoteAdapter.service (CoyoteAdapter.java:293) at org.ap ache.coyote.http11.Http11Processor.process (Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol $ Http11ConnectionHandler.process (Http11Protocol.java:602) на org.apache.tomcat.util.net. JIoEndpoint $ Worker.run (JIoEndpoint.java:489) at java.lang.Thread.run (Thread.java:662) Вызвано: java.sql.BatchUpdateException: Дублировать запись «4-1» для ключа «PRIMARY» на com.mysql.jdbc.PreparedStatement.executeBatchSerially (PreparedStatement.java:2018) в com.mysql.jdbc.PreparedStatement.executeBatch (PreparedStatement.java:1449) в com.mchange.v2.c3p0.impl.NewProxyPreparedStatement. executeBatch (NewProxyPreparedStatement.java:1723) на org.hibernate.jdbc.BatchingBatcher.doExecuteBatch (BatchingBatcher.Java: 70) на org.hibernate.jdbc.AbstractBatcher.executeBatch (AbstractBatcher.java:268) ... 37 более javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: не удалось выполнить JDBC пакетное обновление на org.hibernate.ejb.AbstractEntityManagerImpl.convert (AbstractEntityManagerImpl.java:1214) в org.hibernate.ejb.AbstractEntityManagerImpl.convert (AbstractEntityManagerImpl.java:1147) в org.hibernate.ejb.AbstractEntityManagerImpl.convert (AbstractEntityManagerImpl.java : 1153) at org.hibernate.ejb.AbstractEntityManagerImpl.flush (AbstractEntityManagerImpl.java:798) at play.db.jpa.JPABase._save (JPABase.java:47) at play.db.jpa.GenericModel.save (GenericModel.java:184)на models.UserProfile.saveUser (UserProfile.java:401) в controllers.JTLeadsController.saveLead (JTLeadsController.java:202) в sun.reflect.NativeMethodAccessorImpl.invoke0 (нативный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) на sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) на java.lang.reflect.Method.invoke (Method.java:597) в play.mvc.ActionInvoker.invokeWithContinuation (ActionInvoker.java:546) at play.mvc.ActionInvoker.invoke (ActionInvoker.java:500)

+1

это действительно неясно, в чем проблема ... это выглядит совершенно нормально, чтобы достичь «места 2», если вы дважды нажмете с теми же параметрами! И что вы подразумеваете под «дает ошибку, которая« saved.already »'? код пытается извлечь строку перевода ... что такое ошибка? – Stefano

+0

Спасибо Stefano. Ошибка заключается в том, что он говорит: org.hibernate.exception.ConstraintViolationException: не удалось выполнить пакетное обновление JDBC на org.hibernate.exception.SQLStateConverter.convert (SQLStateConverter.java:96) at org.hibernate.exception.JDBCExceptionHelper.convert (JDBCExceptionHelper.java:66) at org.hibernate.jdbc.AbstractBatcher.executeBatch (AbstractBatcher.java:275) hibernate пытается запустить вставку для уже сохраненного энтузиазма вместо обновления. –

+1

Это помогает, но недостаточно :). В сообщении об ошибке вы должны получить точный номер строки, повышающий ошибку от вашего кода. Не могли бы вы разместить оставшуюся часть сообщения об ошибке и пометить соответствующие номера строк в своем коде? – Stefano

ответ

1

У вас есть три места возможных ошибок:

  • Место 1: Этот вызов метода (Сохранено задание для работы = SavedJob.findByUserIdJobId (connectedUserID(), jobId); // place 1) возвращает null, хотя уже имеется SavedJob. Вы должны проверить код, создающий запрос.
  • место 2: На вашей стороне клиента вы дважды запускаете событие ajax (например, добавив несколько кнопок onclick к кнопке или не отключив кнопку после первого щелчка, чтобы двойной щелчок дважды загорелся) ... это означает, что ваш метод также выполняется дважды. Однако при нормальных обстоятельствах он должен найти задание и вернуть сообщение проверки. Если, однако,
  • место 3: Вы используете базу данных, которая не поддерживает транзакции. Обычная база данных (mysql, postgresql, oracle, db2 и т. Д.) Будет внутренне сериализовать вставки, и ваш код должен работать отлично.
+0

Thanks Dorn. Я могу подтвердить, что точки 1 и 2 не являются проблемой. вызов метода в точке 1 возвращает объект обратно. пункт 2, вызов также прекрасен. Я попытался распечатать ключи объектов для двух запросов непосредственно перед сохранением, а ключи - разные (уникальные). Я использую mysql. Одна вещь, что если я отправлю запрос 1 и 2 в промежутке 4-5 секунд, тогда он отлично работает.Если я отправлю два запроса почти сразу, как-то спящий может: t выяснить, что старый объект уже сохранен, а вместо него - вставка, а не обновление. Когда я сохраняю «UserProfile.saveUser (userProfile)»; Я выполняю слияние. –

+0

hmm ... попытайтесь сохранить задание, а не файл userprofile. Проверьте, как вы сконфигурировали каскадирование сохранения/слияния и т. Д. .. похоже, что проблема здесь. –

+0

экономя только работу. спасительный родитель должен был работать, но теперь уверен, почему. Спасибо за помощь. –

Смежные вопросы