When using Hibernate version 6.4.4.Final, calling the save method of JpaRepository did not trigger an update SQL statement, whereas it did when using version 5.4.15.Final.
Below is my code:
public interface CustomObjectRepository extends JpaRepository<CustomObject, CustomObjectPK> {
}
@Service
public class CustomObjectService {
@Autowired
private CustomObjectRepository customObjectRepository;
@Transactional
public void updateCounts(CustomObjectPK customObjectPK, long currentCounts) {
long previousCounts = customObjectRepository.findById(customObjectPK).map(entity -> entity.getCounts())
.orElse(0L);
CustomObject customObject = new CustomObject();
customObject.setCustomObjectPK(customObjectPK);
customObject.setLastUpdatedTime(new Date());
customObject.setCounts(previousCounts + currentCounts);
customObjectRepository.save(customObject);
}
}
@Getter
@Setter
@Entity
@Table(name = "CUSTOM_OBJECT")
public class CustomObject {
@EmbeddedId
private CustomObjectPK customObjectPK;
@Column(name = "COUNTS", nullable = false)
private long counts;
@Column(name = "LAST_UPDATED_TIME")
private Date lastUpdatedTime;
public CustomObject() {}
public CustomObject(CustomObjectPK customObjectPK) {
this.customObjectPK = customObjectPK;
}
}
@Getter
@Setter
@Embeddable
public class CustomObjectPK implements Serializable {
private static final long serialVersionUID = -8508836212101729149L;
@Column(name = "INSTANCE_ID", nullable = false, length = 100)
private String instanceId;
@Column(name = "UUID", nullable = false, length = 100)
private String uuid;
@Column(name = "TAG", nullable = false, length = 50)
private String tag;
@Column(name = "PART", nullable = false, length = 6)
private String part;
public CustomObjectPK() {
super();
}
public CustomObjectPK(String instanceId, String uuid, String tag, String part) {
super();
this.instanceId = instanceId;
this.uuid = uuid;
this.tag = tag;
this.part = part;
}
}
When I execute the updateCounts method and currentCount is 1, and there was no data for the given PK before, the save method can execute an insert SQL statement. However, if there was data for the PK before and previousCount was 1, the save method does not execute an update SQL statement.
I understand that if all parameters remain unchanged, an update SQL will not be executed. However, since the count increased by 1, I’m wondering why an update SQL statement is not being executed in Hibernate 6.4.4.Final.
A merge call does not necessarily require an immediate flush operation. Usually, the flush is deferred until a transaction ends to avoid holding locks for a long time.
If you want to see the update statement happen immediately, use saveAndFlush() or whatever the Spring Data method is called. Note that this is not a Spring forum, so you usually will not find answers for such Spring questions.
Thank you for the response! However, even when I use the saveAndFlush method, it still does not execute the update SQL. Currently, I found that the following code can execute the update SQL correctly:
@Service
public class CustomObjectService Service {
@Autowired
private CustomObjectRepository customObjectRepository;
@Transactional
public void updateCounts(CustomObjectPK customObjectPK, long currentCounts, String protocol) {
CustomObject customObject = customObjectRepository.findById(customObjectPK).orElse(new CustomObject(customObjectPK));
customObject.setLastUpdatedTime(new Date());
customObject.setCounts(customObject.getCounts() + currentCounts);
customObject.setProtocol(protocol);
customObjectRepository.save(customObject);
}
}
However, if I add the following line of code, the save method no longer executes the update SQL:
customObject.setCustomObjectPK(customObject);
I tried updating data in other tables and found that only tables using @EmbeddedId fail to execute the update SQL properly after setting its primary key.
Below is my CustomObjectPK override method:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
result = prime * result + ((part == null) ? 0 : part.hashCode());
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CustomObjectPK other = (CustomObjectPK) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
if (part == null) {
if (other.part != null)
return false;
} else if (!part.equals(other.part))
return false;
if (instanceId == null) {
if (other.instanceId != null)
return false;
} else if (!instanceId.equals(other.instanceId))
return false;
if (tag == null) {
if (other.tag != null)
return false;
} else if (!tag.equals(other.tag))
return false;
return true;
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
If you think this is a Hibernate ORM bug, please try to create a reproducer with our test case template and if you are able to reproduce the issue, create a bug ticket in our issue tracker and attach that reproducer.