5

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?

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
Daniel Pop
  • 456
  • 1
  • 6
  • 23
  • It will only delay the execution of the select and probably because you haven't enabled partial updates it still is a full update. The accepted answer is the wrong answer (as you will also notice if you read the comments). – M. Deinum Mar 10 '21 at 18:41
  • @M. Deinum then how could I enable partial uploads? – Daniel Pop Mar 10 '21 at 18:55
  • 2
    What has a partial upload to do with a partial update? If you only want partial updates, you can use the `@DynamicUpdate` annotation from Hibernate on your entities. Which will only issue an update query for the modified fields. – M. Deinum Mar 11 '21 at 06:38
  • I meant partial updating, sorry. 'Twas a typo. – Daniel Pop Mar 11 '21 at 08:08
  • @M.Deinum ah there's a Hibernate specific annotation for that, thanks. – Kayaman Mar 11 '21 at 10:30
  • 1
    @DanielPop Partial update is not always a good thing, for example for caсhing. – v.ladynev Mar 11 '21 at 11:14

1 Answers1

4

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.

Kayaman
  • 72,141
  • 5
  • 83
  • 121