Search code examples
javajsonhibernatedto

Assign child enity to parent entity without knowing database id from frontEnd and JSON


I'm working on a RESTFUL web application with spring and hibernate. I want to make a new USER entity that has ManyToOne relationship with ROLE entity:

@Entity
@Table(name = "roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    @Column(unique = true)
    private RoleEnum name;
}


@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    private String firstName;
    private String lastName;

    @ManyToOne
    private Role role;
}

In frontEnd html and ajax, I set all fields except ids(id of USER and id of ROLE) and send json string to backend. This is sample json:

{
    "firstName": "john",
    "lastName": "becks",
    "role": {
         "name": "STUDENT"
     }
}

The problem comes here that I want to assign STUDENT role to this new USER that existed in database but I just know its name not id. And I got error from hibernate:

TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

Can anyone help solve this problem?

Thanks in advance!


Solution

  • There are many parts missing in your example, but to put it simply, hibernate does not have the Role instance from the relationship in its persistence context. In other words, it's telling you to persist the new Role before persisting the User. Hibernate is clever, it tracks objects fetched form the database and can distinguish between a new and existing entity.

    Obviously, that is not what you're trying to do, you want to use an existing Role, not create a new one.

    The only way to do that is to load the Role from the database, finding it by using the name, and add that retrieved role to the relationship.

    Something like this:

    public User createUser(final String userFirstName, final String userLastName, final String roleName) {
    
        Role role = roleDao.findByName(roleName);
    
        if(role == null) {
    
            role = new Role(roleName);
            roleDao.save(role);
        }
    
        final User user = new User(userFirstName, userLastName);
        user.addRole(role);
        userDao.save(user);
    
        return user;
    }