Java JPA/Hibernate:表中有多个不必要的实体
我是新来的,在JPA也是新来的!我用以下实体开发了一个小型JPA应用程序: 客户(姓名、姓名、ID)有地址(邮政编码、城市、ID)。这些实体之间的关系是一对一(客户的观点)和一对一(地址的观点) 代码(部分)如下:(不带getter/setter)Java JPA/Hibernate:表中有多个不必要的实体,java,hibernate,jpa,mapping,database-normalization,Java,Hibernate,Jpa,Mapping,Database Normalization,我是新来的,在JPA也是新来的!我用以下实体开发了一个小型JPA应用程序: 客户(姓名、姓名、ID)有地址(邮政编码、城市、ID)。这些实体之间的关系是一对一(客户的观点)和一对一(地址的观点) 代码(部分)如下:(不带getter/setter) @实体 公共类AddressEntity实现可序列化{ 私有静态最终长serialVersionUID=1L; @身份证 @GeneratedValue(策略=GenerationType.AUTO) 私有int-id; 私人城市; 私有int-zi
@实体
公共类AddressEntity实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有int-id;
私人城市;
私有int-zipCode;
@纵队
@ElementCollection(targetClass=CustomerEntity.class)
私人名单客户;
公共地址实体(){}
@OneToMany(级联=级联类型.ALL,
fetch=FetchType.EAGER,
mappedBy=“addressentity”)
公共列表getCustomers(){
返回客户;
}
@实体
公共类CustomerEntity实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私钥;
私有字符串preName,姓氏;
@多通(targetEntity=AddressEntity.class,cascade=CascadeType.ALL)
@JoinColumn(name=“Address\u ID”)
私人地址实体地址;
公共CustomerEntity(){}
}
现在我想添加两个人:
1) 巴特·辛普森1234斯普林菲尔德
2) 荷马·辛普森1234斯普林菲尔德
问题是,在地址表中,Springfield出现了两次。但这不是规范化数据库的意义!我怎么知道AddressEntity只有在以前不存在的情况下才被添加
谢谢你的回答,
eniac保留新地址 可能有许多
地址实体
具有相同的城市
和Zipcode
。如果您要求给定的客户属性
与相同的地址
相关,那么您必须使用该特定实体。因此,也可以使用用于Bart for Homer的相同的地址实体
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);
例如,更好的方法可能是形成Zip/HouseNumber的复合PK。这可以确保数据库中已经存在Zip/HouseNumber组合的任何AddressEntity
都将被视为分离的对象,并且当然在数据库中只出现一次
嵌入
您的@ElementCollection
和@OneToMany
都是针对您的CustomerEntity实体的
根据JPA规范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;
}
@实体
公共类AddressEntity实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有int-id;
私人城市;
私有int-zipCode;
@OneToMany(级联=级联类型.ALL,
fetch=FetchType.EAGER,
mappedBy=“address”)//不是addressentity
私人名单客户;
公共地址实体(){}
公共列表getCustomers(){
返回客户;
}
或者,您可以将CustomerEntity定义为一个
@embedded
,而不是一个@entity
。通过这种方式,您可以使用@ElementCollection
从AddressEntity
定位CustomerEntity
,但CustomerEntity
本身不是一个实体,无法独立处理因为它依赖于AddressEntity
,所以可能有更好的方法,但是首先尝试持久化地址,然后将其添加到2个用户并持久化这些用户。为了做到这一点,您必须删除或更改级联类型。自定义属性中的所有
(CascadeType.REFRESH
可能可以)。无论如何,使用ALL似乎有点奇怪,主要是因为在您当前的代码中,删除一个客户将删除可能分配给另一个用户的地址。谢谢您的建议!但是您描述的方式与以前的效果相同。其中一些问题取决于您处理的实体的附加性,您可以添加摘录吗保留这些实体的代码是什么?谢谢你的回答。删除@ElementCollection并选择注释方式并不能解决问题problem@Eniac-请参阅更新,您的地址实体是不同的实体,将保留两次,您需要确保在fac中将客户与相同的地址实体关联不打算用作同一地址。
CustomerEntity homer = new CustomerEntity();
homer.setAdress(detachedAddress);
yourEntityManager.merge(homer);
@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;
}