Home > Blockchain >  object in persistent state don't saved to the database, but successfully loaded from it
object in persistent state don't saved to the database, but successfully loaded from it

Time:12-05

My last line of code outputs "role111" (data fetched from database), but after code gets executed I have "role11" in database, so why I have "role11" but not "role111"? Before session get closed role are in the persistent state so it should be connected with row in database and be consistent with it. Maybe a persistent state applicable only inside transaction and last line of code prints role111 due to first level cache.

@Entity
@Table(name = "roles")
public class Role
{
    @Id
    @Column(name = "id")
    private int id;
    
    @Column(name = "name")
    private String name;
    
    public Role()
    {
    }
    
    public int getId()
    {
        return id;
    }
    
    public void setId(int id)
    {
        this.id = id;
    }
    
    public String getName()
    {
        return name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
}
Role role = new Role();
role.setId(1);
role.setName("role1");
        
SessionFactory sessionFactory = new Configuration().configure().addAnnotatedClass(Role.class).buildSessionFactory();
try (Session session = sessionFactory.openSession())
{
    session.beginTransaction();
    session.save(role);
    role.setName("role11");
    System.out.println(session.get(Role.class, 1).getName()); // prints role11
    session.getTransaction().commit();
    role.setName("role111");
    System.out.println(session.get(Role.class, 1).getName()); // prints role111
}

Here is my database

id name
1 role11

CodePudding user response:

The data has not been committed to the database. You need to call commit() again to write it (I assume). Also, sometimes JPA buffers data before issuing a batch of queries. If this is the case, it stands and waits for more data before being necessary to execute them in a burst. If you want to control the process, you can call session.flush() after the last call.

CodePudding user response:

Your assumption in the question title that the data is loaded from the database is incorrect. The data is loaded from the current context that Hibernate is managing, meaning you’ll see the data as it is in memory, which doesn’t imply it has been committed or even updated in the database yet.

CodePudding user response:

Hibernate uses transactional write behind. The hibernate session stores update actions until a commit occurs, at which time the actions get executed, in whatever order Hibernate thinks makes the most sense (as opposed to the order in which they occur in your code), which causes the jdbc updates to process in the database.

The commit following setting the role name to role11 causes the updates to be flushed so the name is saved successfully. Since you don't have a commit following the point where the role name changes to role111, nothing causes the update actions to be run.

You can change what prompts the updates to run by setting the flush mode. If you don't, the default for Hibernate is to flush on commit, unless Hibernate is being used as a JPA provider, in which case it also flushes when a query is run.

  • Related