@CollectionOfElements没有创建适当的表

时间:2010-06-02 20:13:14

标签: java hibernate jpa annotations

修改

大家好。

我尝试获取

我想要一个代表个人详细信息列表的表,这个表名为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都不熟悉,那么我的主要错误在哪里?

我希望现在更容易理解......抱歉我的英语不好。

感谢。

3 个答案:

答案 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() {
}

...

我没有更改其他课程。

这是正确的还是偶然的?

感谢。