У меня есть следующие две сущности:
Человек.java:
@Entity
@Table(name="PERSON")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "person", optional = false)
private Address address;
public Person(final String firstName, final String lastName, final Address address)
{
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
}
//Required by hibernate
public Person()
{
}
public int getId()
{
return id;
}
public String getFirstName()
{
return firstName;
}
public String getLastName()
{
return lastName;
}
public Address getAddress() {
return address;
}
public void setId(final int id)
{
this.id = id;
}
public void setFirstName(final String firstName)
{
this.firstName = firstName;
}
public void setLastName(final String lastName)
{
this.lastName = lastName;
}
public void setAddress(final Address address)
{
this.address = address;
}
}
Адрес.java:
@Entity
@Table(name = "ADDRESS")
public class Address
{
@Id
private int personId;
@MapsId
@OneToOne()
private Person person;
@Column(name = "street")
private String street;
@Column(name = "town")
private String town;
@Column(name = "postcode")
private String postcode;
public Address()
{
}
public Address(final String street, final String town, final String postcode)
{
this.street = street;
this.town = town;
this.postcode = postcode;
}
public Person getPerson()
{
return person;
}
public void setPerson(final Person person)
{
this.person = person;
this.personId = person.getId();
}
public String getStreet()
{
return street;
}
public void setStreet(final String street)
{
this.street = street;
}
public String getTown()
{
return town;
}
public void setTown(final String town)
{
this.town = town;
}
public String getPostcode()
{
return postcode;
}
public void setPostcode(final String postcode)
{
this.postcode = postcode;
}
}
Я хотел бы сопоставить эти два объекта со следующей схемой:
CREATE TABLE person (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(50) NULL DEFAULT NULL,
last_name VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE TABLE address (
person_id INT(10) NOT NULL,
street VARCHAR(50) NULL DEFAULT NULL,
town VARCHAR(50) NULL DEFAULT NULL,
postcode VARCHAR(50) NULL DEFAULT NULL,
FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE
);
Обратите внимание, что таблица адресов не имеет первичного ключа, а только внешний ключ для таблицы лиц. Это означает, что адрес не может существовать без лица, связанного с ним, и что сопоставление должно быть однозначным.
К сожалению, аннотации Hibernate работают некорректно. Это код, который я использую для проверки вышеизложенного:
public static Person save(Person person) {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Integer id = (Integer)session.save(person);
person.setId(id);
session.getTransaction().commit();
session.close();
return person;
}
@Test
public void testWritePerson() {
Person person = new Person("Jack", "Bauer", new Address("123 Fake Street", "Springfield", "SP1F 123"));
person.getAddress().setPerson(person);
Person savedPerson = PersonTestUtil.save(person);
assertFalse(
}
Но ошибка, которую я получаю:
org.hibernate.id.IdentifierGenerationException: null id generated for:class Address
Я пробовал много перестановок различных аннотаций без успеха. Любые идеи, как я могу исправить аннотации в приведенном выше коде, чтобы он правильно сохранял объекты Person и Address? Полный код, если вы хотите протестировать его самостоятельно, находится здесь вместе с инструкциями по настройке базы данных: