JpaRepository getOne() fetches and updates whole object

Viewed 252

I am trying to mimic this accepted SO answer https://stackoverflow.com/a/39746931/3214777 to use a Hibernate Proxy when updating only a field of some objects. My code looks like:

  @Transactional
public void updateStudentYear(int uniqueNumber, int newYear) {
    Student studentProxy = studentRepository.getOne(uniqueNumber);
    studentProxy.setYear(newYear);
    studentRepository.save(studentProxy);
}

The problem is that Hibernate does both a full select and a full update. Here be the logs:

2021-03-10 20:24:23.240 DEBUG 118757 --- [ main] org.hibernate.SQL : select student0_.unique_number as unique_n1_1_0_, student0_.name as name2_1_0_, student0_.team as team3_1_0_, student0_.year as year4_1_0_ from students student0_ where student0_.unique_number=?

2021-03-10 20:24:23.268 DEBUG 118757 --- [ main] org.hibernate.SQL : update students set name=?, team=?, year=? where unique_number=?

I was expecting that only one "update year" statement would be issued, but to my surprise, it looks that everything was done like a classic findOne()/save() pair of operation. Am I wrong?

1 Answers

No, the answer in the linked question is wrong unfortunately. The getOne()/getReference() method isn't about updating individual fields, it's about avoiding hitting the database unless needed.

The usefulness of the method is in situations like

Foo foo = fooRepo.findOne(id);
Bar barProxy = barRepo.getOne(id);
foo.setBar(barProxy);
fooRepo.save(foo);

In this case Foo will be fetched from the db, but Bar will not.

JPA will always update all fields in the update statements, although I'm not sure if it can be affected with implementation's own dirty checking. Hibernate has @DynamicUpdate that limits the columns, but JPA doesn't specify a general mechanism for it.

Related