0

User:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String name;

    @OneToOne(mappedBy = "user")
    private Address address;


    //Getters and setters
}

Address:

@Entity
public class Address {
    @Id
    private Long id;

    @Column
    private String country;

    @OneToOne
    @JoinColumn(name = "id")
    @MapsId
    private User user;


    //Getters and setters
}

Below is the error I am getting:

2020-05-02 02:33:42 - Uncaught Runtime Exception
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance

User and Address classes both share the same Primary key..

Could you please tell me what still I have to change in my above code? I have written above based on some example I found, I will be glad if someone could explain me whats happening internally

EDIT:

I am trying to insert User having RequestBody as below, then facing above exception.

{
    "name": "john",
    "adddress": {
        "country": "US"
    }
}
john
  • 925
  • 1
  • 12
  • 20

2 Answers2

0

You need to cascade the relationship. In User entity, change the relationship to:

@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)

This will propagate any operation from parent to child entity, ie, from User to Address here. So, when you will persist an User object, associated Address object will be persisted as well and so on.


Further Reading:

Community
  • 1
  • 1
Minar Mahmud
  • 2,577
  • 6
  • 20
  • 32
  • After I gave above cascadeType, I am getting another error now: org.springframework.orm.jpa.JpaSystemException: attempted to assign id from null one-to-one property [Address.user]; nested exception is org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [Address.user] – john May 02 '20 at 13:59
  • Can you please post the codes where you initializing and persisting? – Minar Mahmud May 02 '20 at 14:01
  • I am using Spring Data JPA (ie., my DAO interfaces just extends CrudRepository). Is that possible for you to provide me working code having @OneToOne MapsId ? – john May 02 '20 at 14:03
  • In Controller, all I have is userRepository.save(user), thats it! – john May 02 '20 at 14:32
  • Well I'm not sure if yours is the proper use case of `@MapsId`. See this link from hibernate guide with example codes https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#identifiers-derived – Minar Mahmud May 02 '20 at 14:35
  • Hmm.. Thats okay, I will look into above one later. Atleast do you aware for this: https://stackoverflow.com/questions/61561728/how-to-store-multivaluemap-in-mysql-using-jpa-hibernate – john May 02 '20 at 15:21
0

You need to make 2 modifications:

  • add cascade @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
  • make sure that both:
    • address points to user
    • user points to address

The latter is typically accomplished via a custom setter, that sets both sides of the relationship

public void setAddress(Address address) {
    if (address == null) {
        if (this.address != null) {
            this.address.setUser(null);
        }
    }
    else {
        address.setUser(this);
    }
    this.details = details;
}

Please check that this is called when deserializing JSON to your entities.

Lesiak
  • 22,088
  • 2
  • 41
  • 65