gpt4 book ai didi

java - JPA 持久化具有一对多关系的实体

转载 作者:搜寻专家 更新时间:2023-10-30 21:00:42 25 4
gpt4 key购买 nike

配置

  • EcliplseLink 2.3.2
  • JPA 2.0
  • 实体是使用 Entity Classes from Database... 向导从 netbeans 的数据库模式自动创建的。
  • Controller 类是使用 JPA Controller Classes from Entity Classes... 向导从 netbeans 自动创建的

问题的简短版本

在经典场景中,两个表具有一对多关系。我先创建父实体,然后创建子实体,然后将子实体附加到父实体的集合中。当我创建( Controller 方法)父实体时,我希望子实体被创建并与父实体相关联。为什么没有发生?

长版

父类

@Entity
@XmlRootElement
public class Device implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
private Integer id;
@Column(unique=true)
private String name;
@Temporal(TemporalType.TIMESTAMP)
private Date updated;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "deviceId")
private Collection<NetworkInterface> networkInterfaceCollection;

public Device() {
}

public Device(String name) {
this.name = name;
updated = new Date();
}

// setters and getters...

@XmlTransient
public Collection<NetworkInterface> getNetworkInterfaceCollection() {
return networkInterfaceCollection;
}

public void setNetworkInterfaceCollection(Collection<NetworkInterface> networkInterfaceCollection) {
this.networkInterfaceCollection = networkInterfaceCollection;
}

public void addNetworkInterface(NetworkInterface net) {
this.networkInterfaceCollection.add(net);
}

public void removeNetworkInterface(NetworkInterface net) {
this.networkInterfaceCollection.remove(net);
}
// other methods
}

子类

@Entity
@Table(name = "NETWORK_INTERFACE")
@XmlRootElement
public class NetworkInterface implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
private Integer id;
private String name;
@Temporal(TemporalType.TIMESTAMP)
private Date updated;
@JoinColumn(name = "DEVICE_ID", referencedColumnName = "ID")
@ManyToOne(optional = false)
private Device deviceId;

public NetworkInterface() {
}

public NetworkInterface(String name) {
this.name = name;
this.updated = new Date();
}

// setter and getter methods...

public Device getDeviceId() {
return deviceId;
}

public void setDeviceId(Device deviceId) {
this.deviceId = deviceId;
}
}

主类

public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("wifi-dbPU");
DeviceJpaController deviceController = new DeviceJpaController(emf);
NetworkInterfaceJpaController netController = new NetworkInterfaceJpaController(emf);

Device device = new Device("laptop");
NetworkInterface net = new NetworkInterface("eth0");

device.getNetworkInterfaceCollection().add(net);
deviceController.create(device);
}
}

此类在行中抛出 NullPointerException:device.getNetworkInterfaceCollection().add(net);

系统知道有一个新实体 device 并且它的集合中有一个元素 net。我希望它在 db 中写入 device,获取设备的 id,将其附加到 net 并将其写入 db。

而不是这个,我发现这些是我必须做的步骤:

deviceController.create(device);
net.setDeviceId(device);
device.getNetworkInterfaceCollection().add(net);
netController.create(net);

当父类知道它是子类并且应该为我创建它时,为什么我必须创建子类?

DeviceJpaController 的创建方法(抱歉,字段中的名称很长,它们是自动生成的)。

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();
}
}
}

最佳答案

我终于理解了持久化一对多实体背后的逻辑。过程是:

  1. 创建父类
  2. 坚持下去
  3. 创建子类
  4. 将 child 与 parent 联系起来
  5. 持久化子集合(更新父集合)

附代码:

public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("wifi-dbPU");
DeviceJpaController deviceController = new DeviceJpaController(emf);
NetworkInterfaceJpaController netController = new NetworkInterfaceJpaController(emf);

Device device = new Device("laptop"); // 1
deviceController.create(device); // 2

NetworkInterface net = new NetworkInterface("eth0"); // 3
net.setDeviceId(device.getId()); // 4
netController.create(net); // 5
// The parent collection is updated by the above create
}
}

现在,我可以找到一个设备(例如带有 id 的设备)并且我可以让它的所有子设备使用

Collection<NetworkInterface> netCollection = device.getNetworkInterfaceCollection()

在我在问题中发布的设备实体类中,不需要方法 addNetworkInterfaceremoveNetwokrInterface

关于java - JPA 持久化具有一对多关系的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14130041/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com