Question

Ci-dessous mon code de test:

package jee.jpa2;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test
public class Tester {
    EntityManager em;
    EntityTransaction tx;
    EntityManagerFactory emf;

    @BeforeClass
    public void setup() {
        emf = Persistence.createEntityManagerFactory("basicPU", System.getProperties());
    }

    @Test
    public void insert() {
        Item item = new Item();
        for (int i = 0; i < 1000; ++i) {
            em = emf.createEntityManager();
            tx = em.getTransaction();
            tx.begin();
            item.setId(null);
            em.persist(item);
            tx.commit();
            em.clear();
            em.close();
            tx=null;
            em=null;
        }
    }

    @Test
    public void read() {
        em = emf.createEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Query findAll = em.createNamedQuery("findAll");
        List<Item> all = findAll.getResultList();
        for (Item item : all) {
            System.out.println(item);
        }
        tx.commit();
    }
}

Et est l'entité ici:

package jee.jpa2;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;

@Entity
@NamedQuery(name="findAll", query="SELECT i FROM Item i")
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", nullable = false, updatable= false)
    protected Long id;
    protected String name;

    public Item() {
        name = "Digambar";
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return String.format("Item [id=%s, name=%s]", id, name);
    }

}

Après l'exécution de test, j'obtiens l'erreur:

Item [id=1, name=Digambar]
Item [id=2, name=Digambar]
PASSED: read
FAILED: insert
<openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.EntityExistsException: Attempt to persist detached object "jee.jpa2.Item-2".  If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.
FailedObject: jee.jpa2.Item-2
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2563)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2423)
    at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1069)
    at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:705)
    at jee.jpa2.Tester.insert(Tester.java:33)

S'il vous plaît expliquer ce qu'il se passe ici?

Était-ce utile?

La solution

Pour répondre strictement le titre de la question, la mise en valeur d'exécution est effectuée à l'aide d'un javaagent qui peut être chargé dynamiquement lors de l'utilisation JDK 1.6 (ce qui est documenté dans Entité de mise en valeur ).

En ce qui concerne le problème que vous êtes confronté, je soupçonne que ce soit un bug OpenJPA (je l'ai vu plusieurs similaires questions comme OpenJPA-755 ), le message d'erreur est incohérent avec votre code puisque vous configurez le champ de clé primaire null et ne pas la version champ. Vous devez le signaler.

Cela étant dit, un moyen facile de « contourner » la question serait de créer une nouvelle instance de Item dans la boucle. Quelque chose comme ceci:

public void insert() {
    for (int i = 0; i < 1000; ++i) {
        Item item = new Item();
        em = emf.createEntityManager();
        tx = em.getTransaction();
        tx.begin();
        em.persist(item);
        tx.commit();
        em.clear();
        em.close();
        tx=null;
        em=null;
    }
}

Notes complémentaires:

Pourquoi vous passez System.getProperties() lors de la création du EntityManagerFactory?

Vous devez fermer la EntityManagerFactory à la fin de votre test:

@AfterClass
public static void closeEntityManagerFactory() {
    emf.close();
}

Mise à jour: Pour répondre à un commentaire. De la spécification JPA:

  

3.2 du cycle de vie de l'entité instance

     

Cette section décrit la   opérations EntityManager pour la gestion   Le cycle de vie d'une instance d'entité. Un   instance d'entité peut être caractérisé   comme étant nouveau, géré, détaché, ou   supprimé.

     
      
  • nouveau instance de l'entité a pas d'identité persistante , et n'est pas encore   associée à un contexte de persistance.
  •   
  • géré instance de l'entité est une instance avec une identité persistante   qui est actuellement associé à un   contexte de persistance.
  •   
  • A individuelle instance de l'entité est une instance d'une identité persistante   qui est pas (ou plus) associé   dans un contexte de persistance .
  •   
  • supprimé instance de l'entité est une instance avec une identité persistante,   associé à un contexte de persistance,   qui est prévue pour le retrait de la   base de données.
  •   

Donc, si vous avez une entité indépendante (qui est donc ne sont pas associées à un contexte persistant ) et si vous définissez le Id champs annotés à null (il a donc pas d'identité persistante ), alors vous avez exactement ce que la spécification définit comme une nouvelle entité, quel que soit le comportement OpenJPA. Voilà pourquoi je considère cela comme un bug dans OpenJPA (et le message d'erreur est incohérent de toute façon).

Autres conseils

Point à noter que "Entity Manager assure le suivi des entités par des références Java Object".

Je ne peux persister même objet java / référence encore et encore dans la boucle for si et seulement si je déménage déclaration emf = Persistence.createEntityManagerFactory("basicPU") en boucle. comme ceci:

Liste 1:

Item item = new Item(); 
    for (int i = 0; i < 1000; ++i) { 
        emf = Persistence.createEntityManagerFactory("basicPU");            
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 

Mais si la boucle est comme:

Liste 2:

Item item = new Item(); 
    emf = Persistence.createEntityManagerFactory("basicPU");     
    for (int i = 0; i < 1000; ++i) { 
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 

Je reçois le EntityExistException.

Est-ce que cela signifie que la méthode emf.createEntityManager () retourne la copie en cache de EntityManager qui garde la trace de l'objet point persisté dans l'itération précédente de boucle.? un grand NON. parce que quand j'ai essayé d'exécuter des lignes ci-dessous ..

emf = Persistence.createEntityManagerFactory("basicPU");
        for (int i = 0 ; i<10; i++){
                System.out.println(emf.createEntityManager());
        }

imprimé ..

org.apache.openjpa.persistence.EntityManagerImpl@18105e8
org.apache.openjpa.persistence.EntityManagerImpl@9bad5a
org.apache.openjpa.persistence.EntityManagerImpl@91f005
org.apache.openjpa.persistence.EntityManagerImpl@1250ff2
org.apache.openjpa.persistence.EntityManagerImpl@3a0ab1
org.apache.openjpa.persistence.EntityManagerImpl@940f82
org.apache.openjpa.persistence.EntityManagerImpl@864e43
org.apache.openjpa.persistence.EntityManagerImpl@17c2891
org.apache.openjpa.persistence.EntityManagerImpl@4b82d2
org.apache.openjpa.persistence.EntityManagerImpl@179d854

Ce qui signifie emf.createEntityManager () retourne toujours nouvelle instance de entityManager.

Donc, dans le Listing 1 et Listing 2, j'obtient toujours nouvelle instance EntityManager et encore avec la liste 1 Je peux persister même objet dans la base de données, mais dans le Listing 2 je reçois EntityExistException. Pourquoi donc?

Je pense que si je nouvelle EntityManager dans les deux listes (1 et 2) Je devrais être en mesure de persister même objet dans la base de données, car EntityManager conserve la trace des entités par des références d'objets java et dans chaque itération je nouvelle EntityManager, qui dont savent ou ne devrait pas connaître les références d'objet enregistré / persisté dans la base de données dans l'itération précédente par une autre instance d'objet EntityManager.

Avez-vous eu un coup d'oeil au code source? Il est profond dans les entrailles du noyau:

http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?view=markup

Ligne 2563

2,0 OpenJPA peut installer dynamiquement activateur d'exécution lors de l'exécution sur JDK 1.6 (non JRE), voir docs . Techniquement, ils attachent un agent java dynamiquement en utilisant rel="nofollow API Joindre , wihtout besoin d'option -javaagent.

Ainsi, la classe Item est en fait améliorée et gestionnaire d'entités sait qu'il est persistant une instance détachée malgré l'id null et la fermeture du gestionnaire d'entités.

Le message d'erreur vous indique quel est le problème.

  

Tentative de persister objet détaché "jee.jpa2.Item-2".

Une fois que vous persistez votre entité sur la première boucle, tous les appels à em.persist (..) vous passez réellement dans une entité détachée (non une nouvelle entité). Réglage du champ id NULL ne signifie pas que l'entité est maintenant nouveau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top