修改
大家好。
我尝试获取
我想要一个代表个人详细信息列表的表,这个表名为PERSON,必须包含以下列:
ID NAME SURNAME STREET ID_CITY
好吧,我已经在我的数据库中有一个包含我所在国家/地区所有城市的表,这个表名为MUNICIPALITY并且有这个列:
ID COUNTRY PROVINCE NAME
我写了类 Municipality.java 来重新呈现上面的表,这个类是:
@Entity
public class Municipality implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String country;
private String province;
private String name;
public Municipality() {
}
...
所以,我认为PERSON表的一个很好的实现是编写一个emebedded类Address.java,其中包含一些关于要嵌入Person.java类的人的“地址”的信息。 Address.java simpy包含街道和市政对象:
@Embeddable
public class Address implements Serializable {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ID_CITY")
@Cascade(CascadeType.SAVE_UPDATE)
private Municipality municipality;
@Column(length=45)
private String street;
public Address() {
}
...
地址简单地在 Person.java 类:
中进行了描述@Entity
public class Person implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
private String surname;
@Embedded
private Address address;
public Person() {
}
...
好吧,如果现在我保存一个Person实例:
Person p=new Person();
Address a=new Address();
a.setStreet("bla bla");
Municipality mun=new Municipality();
mun.setName("ZZZ");
a.setMunicipality(mun);
p.setAddress(a);
session.save(p);
一切正常,hibernate创建一个PERSON表我想要的。
问题
但是现在,我还想要一个与市政对象关联的所有地址的列表,所以我没有必要为此做“选择”。 我很高兴我要向市政府添加一份地址:
@CollectionOfElements
private List<Address> addressList;
但是现在如果我保存一个人,hibernate会创建一个新表MUNICIPALITY_ADDRESSLIST:
MUNICIPALITY_ID ID_CITY STREET
上面的表总是包含NULL值...所以完全没用,我不想要它!
我读了一些关于@CollectionOfElements和@OneToMany的文档,我发现我可以定义一个连接表。所以我想把PERSON设置成连接表......
@CollectionOfElements
@JoinTable(name="PERSON")
private List<Address> addressList;
Person的第一次插入效果很好,我获得了PERSON表的方式,并且不再创建MUNICIPALITY_ADDRESSLIST。 但是当我进行第二次插入时,hibernate会在PERSON表中添加一列: MUNICIPALITY_ID
ID STREET NAME SURNAME ID_CITY MUNICIPALITY_ID
MUNICIPALITY_ID始终包含NULL值,为什么要添加此列?
当然我的实现非常糟糕,我对hibernate和JPA都不熟悉,那么我的主要错误在哪里?
我希望现在更容易理解......抱歉我的英语不好。
感谢。
答案 0 :(得分:2)
打击,如果你真的不想要 MUNICIPALITY_ADDRESSLIST 表,你应该使用@Transient而不是@CollectionOfElements
public class Municipality {
@Transient
private List<Address> addressList;
}
如果您使用@CollectionOfElements,Hibernate将始终创建 MUNICIPALITY_ADDRESSLIST 表。如果@Transient没有满足您的需求,请提供有关您想要获得的内容的更多信息
更新
根据您自己提供的信息
人拥有 @Embedded地址,该地址与市政当局有@ManyToOne关系
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Embedded
private Address address;
}
现在,我们的地址
/*
* @Embeddable class MUST implements Serializable
*/
@Embeddable
public class Address implements Serializable {
@ManyToOne
/*
* If you are using Hibernate INSTEAD OF JPA
* Prefer to use @Cascade Hibernate annotation, as shown bellow,
* instead of JPA cascade Attribute
*
* Also notice it can not be null - see nullable Attribute
*/
@Cascade(CascadeType.SAVE_UPDATE)
@JoinColumn(name="MUNICIPALITY_ID", nullable=false)
private Municipality municipality;
}
和市政当局(没有任何地址或人员名单)
public class Municipality {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
}
如上所示,您的数据库结构应该是
PERSON
ID
MUNICIPALITY_ID
MUNICIPALITY
ID
但是,市政当局是否有如下人员名单
public class Municipality {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany
private List<Person> personList;
}
您将获得上面显示的相同结构
但你有双向关系人可以看到市政(通过地址类)和市政当局可以看到人(通过人员名单)
现在让我们看看以下场景
Person person = new Person();
Municipality municipality = new Municipality();
Address address = new Address();
address.setMunicipality(person);
person.setAddress(address);
session.save(person);
你会看到
INSERT INTO PERSON blah, blah, blah...
由于@Cascade(SAVE_UPDATE)
INSERT INTO MUNICIPALITY blah, blah, blah...
但由于双向关系,您应该设置哪个属性是该关系的所有者。关系的所有者?那是什么?
假设
public class A {
@ManyToOne
private B b;
}
并且
public class B {
@OneToMany
@JoinColumn(name="B_ID")
@Cascade(SAVE_UPDATE)
private List<A> aList;
}
你做了
/*
* a.getB() is null, right ?
A a = new A();
B b = new B();
b.getAList().add(a);
SQL输出
/* Let's suppose B_ID generated value is 5
INSERT INTO B
/*
* because of @Cascade(SAVE_UPDATE)
INSERT INTO A (B_ID) VALUES(5)
但是因为a.getB()为null
你也会看到
UPDATE A SET B_ID = null
它解释了为什么在使用双向关系时应该使用mappedBy属性。
答案 1 :(得分:1)
我不确定预期的结果究竟是什么(我懒得再现这个案例)但你应该能够得到以下样本:
@org.hibernate.annotations.CollectionOfElements(targetElement = java.lang.String.class)
@JoinTable( name="PHONE",joinColumns = @JoinColumn(name="STUDENT_ID"))
@Column(name="PHONE_NO")
public Set<String> getPhones() {
答案 2 :(得分:1)
最后我想找到一个解决方案......我这样做:
@Entity
public class Municipality implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String country;
private String province;
private String name;
@OneToMany(mappedBy="address.municipality")
private List<Person> persons;
public Municipality() {
}
...
我没有更改其他课程。
这是正确的还是偶然的?
感谢。