config
dans un scénario classique, deux tables avec une autre relation. Je crée l'entité mère, puis l'entité enfant et je joins l'enfant à la collection du parent. Lorsque je créer em> (méthode du contrôleur), l'entité mère, je m'attends à ce que l'entité enfant soit créée et associée au parent. Pourquoi ça ne va-t-il pas? P> version longue forte> p> classe parent p> classe enfant classe principale p> cette classe jette une nullpoinpointException en ligne: Le système sait qu'il existe une nouvelle entité au lieu de cela, j'ai trouvé que ce sont les étapes que je dois faire: p> La méthode de création de périphériqueJpacontroller (désolé pour les noms longs dans les champs, ils sont générés automatiquement). P> périphérique.getNetworkInIncollection (). Ajouter ( NET); code> p>
périphérique code> et il a un élément
net code> dans sa collection. Je m'attendais à écrire
périphérique code> dans dB, d'obtenir l'identifiant de l'appareil, joignez-le à
net code> et écrivez-le dans dB. P>
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(Device device) {
if (device.getNetworkInterfaceCollection() == null) {
device.setNetworkInterfaceCollection(new ArrayList<NetworkInterface>());
}
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
Collection<NetworkInterface> attachedNetworkInterfaceCollection = new ArrayList<NetworkInterface>();
for (NetworkInterface networkInterfaceCollectionNetworkInterfaceToAttach : device.getNetworkInterfaceCollection()) {
networkInterfaceCollectionNetworkInterfaceToAttach = em.getReference(networkInterfaceCollectionNetworkInterfaceToAttach.getClass(), networkInterfaceCollectionNetworkInterfaceToAttach.getId());
attachedNetworkInterfaceCollection.add(networkInterfaceCollectionNetworkInterfaceToAttach);
}
device.setNetworkInterfaceCollection(attachedNetworkInterfaceCollection);
em.persist(device);
for (NetworkInterface networkInterfaceCollectionNetworkInterface : device.getNetworkInterfaceCollection()) {
Device oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface = networkInterfaceCollectionNetworkInterface.getDeviceId();
networkInterfaceCollectionNetworkInterface.setDeviceId(device);
networkInterfaceCollectionNetworkInterface = em.merge(networkInterfaceCollectionNetworkInterface);
if (oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface != null) {
oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface.getNetworkInterfaceCollection().remove(networkInterfaceCollectionNetworkInterface);
oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface = em.merge(oldDeviceIdOfNetworkInterfaceCollectionNetworkInterface);
}
}
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
5 Réponses :
Ceci est un comportement connu des membres de données de collecte. La solution la plus simple consiste à modifier votre collection getter à la création de la collection paresseusement.
@XmlTransient public Collection<NetworkInterface> getNetworkInterfaceCollection() { if (networkInterfaceCollection == null) { networkInterfaceCollection = new Some_Collection_Type<NetworkInterface>(); } return networkInterfaceCollection; }
Ceci est fait dans le DeviceJpacontroller Code> Créer. Voir le si au début. Si la collection est nulle, elle crée une nouvelle et la définit avec la méthode
périphérique.setnetNetWorkIncollection code>. J'ai essayé votre suggestion et je reçois:
IllegalArgumentException: une instance d'un PK NULL a été fournie de manière incorrecte à cette recherche. Code>
@Dima k est correct dans ce qu'ils disent. Lorsque vous faites cela:
NetworkInterface net = new NetworkInterface("eth0"); getEntityManager().persist(net);
Vous avez tous deux besoin de l'initialisation de la collection. Mais c'est ma question. Pourquoi dois-je persister deux entités lorsque tout ce dont j'ai besoin est de créer la collection. Le JPA ne devrait-il pas persister toutes les entités de la collection et les associer à la classe mère?
JPA sait sur les entités et quel état ils sont. Donc, créer une entité de périphérique et une entité de réseaux d'interface. JPA saura sur deux entités. Il est de votre responsabilité de le dire la relation entre les deux. Je comprends ce que vous voulez dire que si vous persistez à l'appareil et que vous ajoutez des éléments à sa collection après, que JPA devrait le perserner aussi. Si la collection est remplie lorsque vous PERSIST CODE> Le périphérique (ou inversement), le périphérique et ses éléments de collections seront persistés.
Cette exception signifie que vous essayez de localiser une entité (probablement par em.getreference ()) qui n'a pas encore été persisté. Vous ne pouvez pas vous être em.getreference () ou em.Find () sur des entités qui n'ont toujours pas de pk. P>
Tu as raison. Il essaie de localiser l'identifiant de Net dans un appel Em.GetReference (). L'identifiant est null parce que l'entité n'a pas encore été persistée. S'il vous plaît voir le commentaire à @sotirios Delimanolis Post.
J'ai enfin compris la logique derrière la persistance de l'une à de nombreuses entités. Le processus est:
avec code: p> MAINTENANT, je peux trouver un appareil (avec ID par exemple) et je peux obtenir tous ses enfants en utilisant p> dans la classe d'entité de périphérique, que j'ai posté dans la question, il n'y a pas besoin de méthodes addnetworkinterface code> et
removeetwokrinterface code>. < / p> p>
Selon ce que j'ai lu du livre. Cascade = CascadeType.persist Code> doit persister toutes les relations et il vous suffit de mettre à jour une entité, JPA naviguera à travers les relations et mettra à jour les entités associées. Mais ... je ne pouvais pas le faire travailler ...
Pour activer la capacité d'économie sur une relation @onetomany, par exemple , vous devez dire à votre relation @manytoone qu'il est autorisé à mettre à jour MyTable comme cette mise à jour = true p>
Updatable = true, insérable = true code> sont des valeurs par défaut de toute façon, cela ne résout pas le problème.