@CollectionOfElements без создания подходящей таблицы - PullRequest
2 голосов
/ 03 июня 2010

EDIT

Привет всем.

ЧТО Я ПЫТАЮСЬ ПОЛУЧИТЬ

Мне нужна таблица, представляющая список личных данных, эта таблица называется 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 ]

2 голосов
/ 03 июня 2010

удар, если вы действительно не хотите MUNICIPALITY_ADDRESSLIST Таблица, вы должны использовать @Transient вместо @ CollectionOfElements

public class Municipality {

    @Transient
    private List<Address> addressList;

}

Если вы используете @CollectionOfElements, Hibernate всегда будет создавать MUNICIPALITY_ADDRESSLIST Таблица. Если @Transient не удовлетворяет вашим потребностям, предоставьте больше информации о том, что вы хотите получить

UPDATE

По информации, предоставленной вами

Person имеет адрес @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 голос
/ 04 июня 2010

Наконец я думаю найти решение ... я делаю это:

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

...

Я не изменил другие классы.

Это правильно или работает случайно?

Спасибо.

1 голос
/ 03 июня 2010

Я не уверен, каков ожидаемый результат (мне лень воспроизводить случай), но вы должны быть в состоянии получить следующий пример:

@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() {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...