Search code examples
javadatabasehibernatejdbchibernate-mapping

How Hibernate session.getTransaction().commit() knows there are private field changes without calling getter?


If I change firstName value by calling setFirstName(String newFirstName) and then commit data with session.getTransaction().commit(), everything works fine, but how Hibernate knows new Student first name without calling getFirstName() in Student class ?

        Session session = sessionFactory.getCurrentSession();

        try{
            session.beginTransaction();
            Student student = session.get(Student.class, 1);
            student.setFirstName("Michael");
            session.getTransaction().commit();
        }

Student class getter:

@Column(name = "first_name")
private String firstName;

public String getFirstName() {
    System.out.println("Getting first name: "+firstName); //never printed
    return firstName;
}

Solution

  • I suspect that in Student entity the @Id annotation is placed on the field and not on the getter. Smth like:

    @Id
    private Long id;
    

    In this case, Hibernate uses the "field-based access type", i.e. it reads or writes all fields of the entity directly (via reflection). So, while performing dirty check, it just reads the values of Student fields (firstName too) without using their getters.

    You can change this behavior to "property-based" access type by placing @Id on the corresponding getter of "id" field.

    Or you can use @AttributeAccessor (or its JPA's equivalent - @Access) to override this behavior.

    There are pros and cons of these 2 access types. Read more about it in the docs.