2

I created a Spring Web Application with database access. I have a class Person - which has references to a class Address. A person has an address as well as the company, so person and company both refer to the Address table. I did this by defining a @ManyToOne relation from person to address as well as the company.

    @ManyToOne
    @JoinColumn (name="COMPANY_ID")
    private Adress companyId;

    @ManyToOne
    @JoinColumn (name="SUBSIDIARY_ID")
    private Adress subsidiaryId;

In the person repository I have a save method like this:

 public Person save(Person entity) {

    SaveAccess<Person> ao = createSaveAccess();

    ao.setEntity(entity);
    ao.execute();
    return ao.getResult();
}

The thing is, if I try to add a new person I get a Hibernate-TransientPropertyValueException which says Object references an unsaved transient instance - save the transient instance before flushing. Can anyone help me here?

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
d_S97
  • 21
  • 1
  • 5

3 Answers3

1

Can you try this

@ManyToOne(cascade = CascadeType.ALL)

    @JoinColumn (name="COMPANY_ID")
    private Adress companyId;

   @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn (name="SUBSIDIARY_ID")
    private Adress subsidiaryId;

reference: Hibernate TransientPropertyValueException When saving data

https://dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-many-to-one-using-annotations-1.html

Community
  • 1
  • 1
Elias
  • 664
  • 2
  • 11
  • 23
  • Thanks for your answer. The thing is, now it works if companyId and subsidiaryId are different and not in the database. But if the subsidiaryId and companyId are the same or one of them is in the database I get a UniqueConstraint Violated exception. – d_S97 Mar 23 '17 at 09:38
  • Do I have to make a bidirectional association here? Something like a OneToMany Mapping in address? Like that: `@OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn(name = "COMPANY_ID") private Set person_companies; @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn(name = "SUBSIDIARY_ID") private Set person_subsidiaries;` – d_S97 Mar 23 '17 at 10:06
  • Did you find a solution how to update company and subsidiary when they're already stored in DB? – Mikhail Kopylov Jun 06 '17 at 06:15
1

I had a similar issue with a @OneToOne annotation of a table called Product to another one called Category. I wanted to specify that every Product has to have a single Category.

Thus, I had to make sure to set the cascade type to be CascadeType.ALL like so:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "CATEGORY_NAME")
private Category category;
Patrick
  • 1,728
  • 2
  • 17
  • 30
0

I don't think so the address contains so much data it justifiable to store as an independent entity. For performance considerations I recommend you to use embeddable + embedded classes for this purpose:

@Embeddable
public class Address
{
  String number;
  String street;
  String city;
  String country;
}

@Entity
public class Person
{
  @Id
  protected long id
  ...
  @Embedded
  Address address;
  @Embedded
  Address companyAddress;
  ...
}

If you have a legacy system and you have to store the addresses in a separate table, there is the @SecondaryTable solution:

@Entity
@Table(name = "EMPLOYEE")
@SecondaryTable(name = "ADDRESS", pkJoinColumns = @PrimaryKeyJoinColumn(name = "EMPLOYEE_ID"))
public class Employee
{
    //...
    @Column(table = "ADDRESS")
    private Address address;

    @Column(table = "ADDRESS")
    private Address companyAddress;
}
The Bitman
  • 1,279
  • 1
  • 11
  • 25
  • Unfortunally I am not able to do this, since it's a requirement to store Addresses in a seperate table in the database. It's because we need addresses not only for people but also for other entities. – d_S97 Mar 23 '17 at 10:38
  • In this case you can apply the @SecondaryTable solution. I have modified my answer. – The Bitman Mar 23 '17 at 11:12
  • The thing is, I need to have a Entity Address too because I have a rest service, that returns them. – d_S97 Mar 23 '17 at 12:08