我是新来的,我也是JPA的新手!我开发了一个带有以下实体的小JPA应用程序:
客户(姓名,名称,ID)有一个地址(ZIP_Code,city,ID)。这些实体之间的关系是ManyToOne(Customer's perpective)和OneToMany(Address'透视图)。
代码(部分)如下:(没有getter / setters)
@Entity
public class AddressEntity implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String city;
private int zipCode;
@Column
@ElementCollection(targetClass=CustomerEntity.class)
private List<CustomerEntity> customers;
public AddressEntity() {}
@OneToMany(cascade=CascadeType.ALL,
fetch=FetchType.EAGER,
mappedBy="addressentity")
public List<CustomerEntity> getCustomers() {
return customers;
}
@Entity
public class CustomerEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int primaryKey;
private String preName, surName;
@ManyToOne(targetEntity=AddressEntity.class, cascade=CascadeType.ALL)
@JoinColumn(name="Address_ID")
private AddressEntity address;
public CustomerEntity() {}
}
现在我要添加两个人: 1)Bart Simpson 1234 Springfield 2)Homer Simpson 1234 Springfield
问题是在地址表中Springfield出现两次。但这不是规范化数据库的意义!我怎么才能意识到AddressEntity只在以前不存在时添加!
感谢您的回答, ENIAC
答案 0 :(得分:0)
保留新地址
可能有许多AddressEntities
具有相同的City
和Zipcode
。如果您要求给定CustomerEntity
与同一address
相关,则必须使用该特定实体。因此,使用与荷兰巴特一样的AddressEntity
CustomerEntity bart = new CustomerEntity();
//Set Barts’s fields.
CustomerEntity homer = new CustomerEntity();
//Set Homers’s fields.
AddressEntity simpsonsPlace = new AddressEntity();
//set 1234 and Springfield.
bart.setAdress(simpsonsPlace);
homer.setAdress(simpsonsPlace);
List<CustomerEntity> simpsons = new ArrayList<CustomerEntity>();
simpsons.add(bart);
simpsons.add(homer);
simpsonsPlace.setCustomers(simpsons);
yourEntityManager.persist(bart);
yourEntityManager.persist(homer);
与现有地址相关联。
如果您在bart之后的某个时间创建本垒打,那么您需要将bart与现有的address
相关联。也许你会从客户端传入address
。这将填充id字段,并且将是分离的实体。您可以将此实体与em.merge()
操作一起使用;
CustomerEntity homer = new CustomerEntity();
homer.setAdress(detachedAddress);
yourEntityManager.merge(homer);
更好的方法可能是形成Zip / HouseNumber的复合PK。这样可以确保DB中已有的任何带有Zip / HouseNumber组合的AddressEntity
将被视为分离对象,当然只会在数据库中出现一次。
<强> Embeddables 强>
您同时将@ElementCollection
和@OneToMany
定位到您的CustomerEntity 实体。
根据JPA Spec 11.1.14;
ElementCollection注释定义了一组实例 基本类型或可嵌入类。
因此使用@ElementCollection
定位实体是不正确的。
您需要两个实体之间的关系,因此,在AddressEntity
您需要使用@OneToMany
并删除@ElementCollection
。您还需要将(mappedBy
)映射到目标类的字段而不是目标类本身;
@Entity
public class AddressEntity implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String city;
private int zipCode;
@OneToMany(cascade=CascadeType.ALL,
fetch=FetchType.EAGER,
mappedBy="address") //Not addressentity
private List<CustomerEntity> customers;
public AddressEntity() {}
public List<CustomerEntity> getCustomers() {
return customers;
}
或者,您可以将CustomerEntity定义为@Embeddable
而不是@entity
。通过这种方式,您可以使用@ElementCollection
从CustomerEntity
定位AddressEntity
,但CustomerEntity
本身不是实体,无法独立处理,因为它依赖于AddressEntity