web-dev-qa-db-ja.com

EntityManagerの更新の問題

更新関数を呼び出すと、EntityManagerからこのエラーが発生します。

public void saveProduct(Product product) {
    entityManager.refresh(product);
}

これはSpring/Hibernateのバグである可能性があると聞きましたが、これを回避する方法がわかりません。

編集:エラーは

Java.lang.IllegalArgumentException: Entity not managed
org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.Java:268)
Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
Java.lang.reflect.Method.invoke(Method.Java:597)
org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.Java:358)
$Proxy17.refresh(Unknown Source)
Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
Java.lang.reflect.Method.invoke(Method.Java:597)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.Java:198)
$Proxy11.refresh(Unknown Source)
springapp.repository.JdbcProductDao.saveProduct(JdbcProductDao.Java:66)
springapp.service.SimpleProductManager.increasePrice(SimpleProductManager.Java:28)
springapp.web.PriceIncreaseFormController.onSubmit(PriceIncreaseFormController.Java:39)
Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
Java.lang.reflect.Method.invoke(Method.Java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.Java:421)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.Java:136)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.Java:326)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.Java:313)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:875)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:571)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.Java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)
23
Albinoswordfish

EntityManager のドキュメントから:

IllegalArgumentException-エンティティまたはエンティティが管理されていない場合

  1. エンティティがマップされているかどうかを確認します(_@Entity_を使用して、または_.xml_構成で)
  2. エンティティはpersistentである必要があります。つまり、entityManagerによって管理されます。したがって、エンティティがデタッチされている場合は、最初にmerge()を実行し、次にrefresh()を実行します。
16
Bozho
public void saveProduct(Product product) {
    ...

    Product managedProductEntity = entityManager.find(Product.class, product.getId());
    entityManager.refresh(managedProductEntity);

    ...
}

このように動作します。 managedProductEntitymanagedになるため、データベースから更新できます。

14
Daniel Szalay

productオブジェクトが作成されたばかりの場合、オブジェクトの元の値を含む行がデータベースにないため、refresh()することはできません。最初にpersist()productを実行し、次にflush()をエンティティマネージャーに送信する必要があります。その後、refresh()を使用できます。

8

オブジェクトがデタッチされている場合は、更新することもできません。バグかもしれません... AbstractEntityManagerImpl(Hibernate 3.6.0.Final?)の730〜733行目を見てください。

    public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
    ...
        if ( !getSession().contains( entity ) ) {
            throw new IllegalArgumentException( "Entity not managed" );
        }
    ...
2
Nick G.

Nullエンティティを渡すと、これと同じエラーが返されます。アプリでこの問題が発生したのは、最初に更新ルーチンを実装したときであり、エンティティがすべて管理されているため、それを理解できませんでした。管理対象エンティティのnullインスタンスは明らかにカウントされません!

1
user2125247