2014-11-14 2 views
0

Я использую JPA с поставщиком гибернации. Heres моя часть кода:JPA merge() на отдельном объекте делает вставку, когда она существует

@Entity 
@IdClass(xxxPK.class) 
@NamedQueries({ 
... 
}) 
@Inheritance(strategy = InheritanceType.JOINED) 
public class xxx extends AbstractEntity { 

public static final String GET_TRADES = "getInstruments"; 
public static final String GET_STRUCTURE = "getStructure"; 
public static final String GET_ALL = "getAllTrades"; 

@Column(nullable = false) 
@Id 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "xxx") 
@SequenceGenerator(name = "xxxx", sequenceName = "xxxxS", allocationSize = 1) 
private Long systemId; 

@Id 
@Column(nullable = false) 
private Integer version; 
////// 

И потомок:

@Entity 
@PrimaryKeyJoinColumns(
    { 
      @PrimaryKeyJoinColumn(name = "systemId"), 
      @PrimaryKeyJoinColumn(name = "version") 
    } 
) 
public class YYY extends xxx { 
////// 

Я создаю экземпляр YYY и persiti как я ожидал. После этого я на одну строку в каждой таблице в дБ:

fx = Persistence.invoke(new Persistence.Invoke<YYY>() { 
      @Override 
      public YYY run(EntityManager em) { 
       BufferedReader reader = null; 
       try { 
        reader = new BufferedReader(new FileReader(new ClassPathResource("json/XXX_from.json").getFile())); 
       } catch (IOException ex) { 
        System.out.print("File is not found"); 
       } 
       YYYfx = (YYY) EntityConverter.getConverter(YYY.class).fromJson(reader); 
       em.persist(fx); 
       return fx; 
      } 
     }); 

Таким образом, после того, что FX отсоединяется и, как SPEC. саис я могу сделать его постоянным в другой сессии, вызвав слияния(), так называю его, но:

Persistence.invoke(new Persistence.Invoke<Object>() { 
    @Override 
    public Object run(EntityManager em) { 
     fx.setZZZ("A"); 
     em.merge(fx); 
     return null; 
    } 
}); 

После этого я иметь другую строку в XXX и YYY таблицах с новым первичным. Похоже, что провайдер принимает fx как TRANSIENT, а не DETACHED, тогда он sais ok - это новый объект, и я бы его вставлял. Я не знаю, что делать, я потерял 4 часа в таком глупом случае. Пожалуйста помоги!

public class Persistence { 

    private static EntityManagerFactory emf; 

    public static EntityManagerFactory getEmf() { 
     return emf; 
    } 

    public void setEmf(EntityManagerFactory emf) { 
     Persistence.emf = emf; 
    } 

    public static <T> T invoke(Invoke<T> inv) { 
     T result = null; 
     EntityManager em = getEmf().createEntityManager(); 
     EntityTransaction transaction = em.getTransaction(); 
     transaction.begin(); 
      try { 
      result = inv.run(em); 
      transaction.commit(); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } finally { 
      em.close(); 
     } 
     return result; 
    } 

    public interface Invoke<T> { 
     public T run(EntityManager em); 
    } 

} 

ответ

1

См API:

https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#merge(T)

Возвращает: управляемый экземпляра, что государство было объединено в

Так что с первого звонка:

return em.persist(fx); 

http://www.objectdb.com/java/jpa/persistence/detach

отдельных объектов, могут быть присоединены к любому EntityManager с помощью метода слияния:

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

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