0

I did this simple Spring Security tutorial. https://www.boraji.com/spring-mvc-5-spring-security-5-hibernate-5-example

Now I want to create a user in my database.

The problem is that I need to create 2 objects dependent on each other and I get

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing:

So What's the solution for this??

  public static boolean createUser(byte[] image, String name, String username, String password, String permissions) {
    String hashedPassword = new BCryptPasswordEncoder().encode(password);
    //check if user already exists
    boolean exists = User.checkIfUserExists(username);
    //if it doesn't add to database
    if(!exists) {
        UserRole userRole = new UserRole();
        User user = new User();
        userRole.setRole(permissions);
        userRole.setUser(user);
        Database.addToDatabase(userRole);
        //user table
        user = new User(image, name, username, true, hashedPassword, userRole);
        Database.addToDatabase(user);
        //user role table
        userRole.setUser(user);
        Database.updateObject(userRole);

        return true;
    }
    else
        return false;
}

//Save the object to the database
public static void addToDatabase(Object object) {
    SessionFactory factory = HibernateUtil.GetSessionFactory();
    Session session = factory.openSession();
    Transaction tx = null;
    try{
        tx = session.beginTransaction();
        session.save(object);
        tx.commit();
    }catch (HibernateException e) {
        if (tx!=null) tx.rollback();
        e.printStackTrace();
    }finally {
        session.close();
    }
}

Basically UserRole already needs to be in db to save User and User needs to be in db to save UserRole.

  • [Possible duplicate][https://stackoverflow.com/questions/2302802/object-references-an-unsaved-transient-instance-save-the-transient-instance-be] – Sr7 Apr 16 '18 at 09:01

1 Answers1

0

That exception means exactly what is written. You have a relationship between two objects. For example UserRole has a linked User. But when you are trying to save the UserRole into the database the User object you have attached to it is not yet saved (it is in transient state) so Hibernate's problem is how to save that user role in the database when the user might not exist (it still doesn't have valid ID in the database ).

There are different ways you can deal with that. One of them is to mark the list as Cascade=ALL (or Cascade=SAVE_UPDATE). This way you will bind these two objects and when you save the user it will automatically save the user role. There are pros and cons with that. The "+" is that it is easier and you will have just one save. The "-" is that you have these objects connected and you might save/update an object by mistake if you are not careful.

Another solution would be to first save the User (without the roles). Then save the roles with the user set to the newly saved user (it should have a real ID in the database). Then add the roles to the user and update it. This way you will not save anything with transient values and you will go around that problem. Also do it in a transaction so you don't have bad data if something breaks.

Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23