2016-04-15 2 views
2

Привет SO СообществоEntityManager Merge Вставки новую сущность

У меня возникли проблемы с Hibernate JPA: всякий раз, когда я называю entityManger.merge(entity), Hibernate пытается вставить ее. Я перешел из OpenJPA, где он работал правильно, но я не могу получить эту работу независимо от того, что я делаю.

Я искал в SO и Google решение проблемы, или, по крайней мере, что-то, что указывает мне в правильном направлении, без везения. Пост, который находится ближе всего к моему вопросу, не был дан ответ: entitymanager merge insert instead of update JPA Hibernate

Я пытаюсь вставить объект Organization который имеет однонаправленный @OneToOne отношения с User лица. Я добавил Casecade.Persist, поэтому объект User затронут только при создании/сохранении Organization. Операция persist работает как ожидалось. Однако, как было указано ранее, merge работает не так, как ожидалось, вместо этого он пытается сохранить/вставить.

Может кто-то, пожалуйста, помогите мне решить эту проблему?

Я хотел бы использовать только JPA Hibernate и избегать конкретных реализаций Hibernate в случае, когда мне когда-либо понадобится перейти на другого поставщика JPA.

Окружающая среда:

Это проект Maven, и я использую Wildfly 10

Ниже мой код:

Я использую MappedSuperClass для обычных полей SQL:

@MappedSuperclass 
public abstract class BaseEntity implements Serializable{ 
    protected static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 

    //[UPDATE] I omitted the version field thinking it wasn't relevant, but now I believe this is the root of my problem. If I remove this field merge works as expected. 
    @Version 
    Long version 
    // getters and setters 
} 

Сущность, которую я пытаюсь вставить:

@Entity 
public class Organization extends BaseEntity{ 

    @Column 
    private String name; 

    @Column 
    private String description; 

    @OneToOne(cascade = CascadeType.PERSIST) 
    @JoinColumn(unique = true, insertable = true) 
    private User user; 

    // getters and setters 
} 

User объект:

@Entity 
public class User extends BaseEntity implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 100) 
    private String username; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 256) 
    private String password; 
    @Size(max = 45) 
    private String firstName; 
    @Size(max = 45) 
    private String lastName; 

    //getters and setters 

} 

Я пытаюсь объединить объект в методе в JAX-RS отдыха:

@Path("{id}") 
@PUT 
@Consumes("application/json") 
@Produces("application/json") 
public Organization edit(Organization entity, 
         @PathParam("id") Long id) { 
    //Omitting how I got the userId as it is not relevant to the situation at hand 
    entity.setUser(entityManager.find(User.class, userId)); 
    super.edit(entity); 

    return entity; 
} 

Примечание:

  • Объект объект выше, который я pas s как объект JSON в запросе и сортируется Jackson, содержит все необходимые поля, [особенно первичный ключ (id)].
  • Оба объекта и MappedSuperClass находятся в постоянстве.XML

Я включил hibernate.show_sql в persistence.xml, чтобы увидеть, что происходит:

<property name = "hibernate.show_sql" value = "true" />

Ниже StackTrace за исключением я получаю:

17:58:08,804 INFO [stdout] (default task-4) Hibernate: insert into Organization (createdBy, lastUpdatedBy, version, description, name, user_id) values (?, ?, ?, ?, ?, ?) 
17:58:09,302 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-4) SQL Error: 1062, SQLState: 23000 
17:58:09,303 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-4) Duplicate entry '1' for key 'UK_5lqexr38qf28ptx0lhuhqor9w' 
17:58:09,401 ERROR [org.jboss.as.ejb3.invocation] (default task-4) WFLYEJB0034: EJB Invocation failed on component OrganizationFacadeREST for method public com.scholarjet.model.Organization com.scholarjet.service.OrganizationFacadeREST.edit(com.scholarjet.model.Organization,java.lang.Long): javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:187) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:277) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:327) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) 
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636) 
    at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) 
    at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195) 
    at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73) 
    at com.scholarjet.service.OrganizationFacadeREST$$$view4.edit(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:436) 
    at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:127) 
    at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) 
    at org.jboss.weld.bean.proxy.InjectionPointPropagatingEnterpriseTargetBeanInstance.invoke(InjectionPointPropagatingEnterpriseTargetBeanInstance.java:67) 
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100) 
    at com.scholarjet.service.OrganizationFacadeREST$Proxy$_$$_Weld$EnterpriseProxy$.edit(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139) 
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295) 
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249) 
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236) 
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:395) 
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:202) 
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221) 
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) 
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) 
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174) 
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) 
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1171) 
    at org.jboss.as.jpa.container.AbstractEntityManager.merge(AbstractEntityManager.java:565) 
    at com.scholarjet.service.AbstractFacade.edit(AbstractFacade.java:32) 
    at com.scholarjet.service.OrganizationFacadeREST.edit(OrganizationFacadeREST.java:110) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93) 
    at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64) 
    at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(PooledInstanceInterceptor.java:51) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275) 
    ... 84 more 
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207) 
    at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57) 
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2792) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3363) 
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597) 
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:232) 
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:213) 
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:256) 
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:317) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:272) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:109) 
    at org.hibernate.jpa.event.internal.core.JpaMergeEventListener.saveWithGeneratedId(JpaMergeEventListener.java:56) 
    at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:255) 
    at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:235) 
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:173) 
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:69) 
    at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:840) 
    at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:822) 
    at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:827) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1161) 
    ... 116 more 
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'UK_5lqexr38qf28ptx0lhuhqor9w' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) 
    at com.mysql.jdbc.Util.getInstance(Util.java:372) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3835) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2535) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1911) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2145) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2081) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2066) 
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) 
    ... 138 more 

[UPDATE]

JSON Объект, представленный в запросе PUT:

{ 
    "id": 1, 
    "name": "2 My Org 1", 
    "description": "2 Org 1 Description 1" 
} 

С точки зрения toString выхода, я не переопределить (переопределен?) toString данного объекта. Так что сейчас он возвращается по умолчанию метод toString в Object:

[email protected]

В случае, если это поможет, я поставил точку останова в строке, где я называю super.edit(entity) и побежал отладчик. Это содержание entity:

Contents of entity when stopped in breakpoint

Я хотел бы также отметить, что super.edit(entity) просто называет: entityManager.merge(entity)

+0

Я должен задать очевидный вопрос: поле pk заполнено до слияния? – dambros

+0

Да, я упоминаю это в сообщении, но, учитывая, что вы его пропустили, это может быть неясно.Я обновляю сообщение, чтобы указать на это. Спасибо за вопрос! –

+0

Не могли бы вы показать отправленный JSON, а также, возможно, вывод toString() значений внутри вашего объекта до вызова слияния? – Naros

ответ

0

Я опустил поле версии думая, что это не имеет отношения, но теперь я считаю, что это является корнем моей проблемы. Если я удалю это поле, слияние будет работать, как ожидалось.

Это из-за того, как @Version и оптимизационно-блокировочная работа.

Я всегда предпочитаю не подвергать внешнему миру @Version собственности, потому что он позволяет внешнему событию принудительно обновлять файлы в тех случаях, когда мне нужен OptimisiticLockException, чтобы его выбросить, когда одна и та же строка будет изменена несколькими сеансами одновременно.

То, что вы хотите сделать, это использовать шаблон объекта переноса и наложения входящих данных поверх реального объекта базы данных:

@Path("{id}") 
@PUT 
@Consumes("application/json") 
@Produces("application/json") 
public Organization edit(OrganizationDTO dto, 
        @PathParam("id") Long id) { 
    // lookup entity from database 
    Organization org = entityManager.find(Organization.class, entity.getId()); 
    // map changable values to the entity 
    org.setName(dto.getName()); 
    org.setDescription(dto.getDescription()); 
    org.setUser(entityManager.find(User.class, userId)); 
    dto.setUser(org.getUser()); 
    // merge changes 
    entityManager.merge(org); 
    // return dto 
    return dto; 
} 

Я считаю, вы можете использовать ObjectMapper, где вы можете делать пометки отображения без обязательно скомпрометировать его; Я оставлю это как упражнение.

Но дело в том, что корень вашей проблемы заключается в том, что вы пытаетесь обработать свои входящие данные JSON полным объектом Organization и попытаться обновить его в своей базе данных, когда на самом деле это частичные данные.

Если значение версии было предоставлено в вашем первоначальном JSON, спящий режим работал бы с объединением, как вы ожидали, предполагая, что указанное значение версии соответствует значению в вашей базе данных. Не равное нулевому значению, которое не соответствовало бы, было бы вызвано OptimisticLockException.

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