Incomplete Object
The parameter of a save command is a dynamic object. If some of the properties are not specified, then the object is an incomplete object.
To demonstrate the value of incomplete objects, let's look at a real example - changing the many-to-one association store
of the Book
with id 8
to null.
It seems there are two ways to implement this functionality:
-
Execute an UPDATE statement via update statements
-
Query the
Book
object, change itsstore
property to null, and save it
Most developers prefer the second approach. So in this article, we will discuss the second approach.
JPA Example
Before introducing Jimmer's support for saving incomplete objects, let's first see how to implement this with JPA:
EntityManager entityManager = ...get JPA session from current transaction context, omitted...
Book book = entityManager.find(Book.class, 8L);
book.setStore(null); // JPA entities are mutable, change association to null
// Calling merge here just for clarity, can be omitted since JPA will update db on tx commit anyway
entityManager.merge(book);
Apart from setting store
to null, we do not know the existing values of other properties. In JPA, constrained by the fixed shape of plain POJO entities, we have to query all properties of the object, modify the store
property (keeping others unchanged), and save the object again.
Even if the object has hundreds of properties, we have to do this, which is obviously wasteful.
Jimmer Example
- Java
- Kotlin
sqlClient.update(
Immutables.createBook(draft -> {
draft.setId(8L);
draft.setStore(null);
})
);
sqlClient.update(
Book {
id = 8L
store = null
}
);
-
Explicitly use
update
(orsave(book, SaveMode.UPDATE_ONLY)
) to indicate this is an update operation, avoiding the probing query of theUPSERT
mode to simplify the discussion. -
Make up a Book object out of thin air, only assigning its
id
property andstore
property, while all other properties are unknown.This incomplete object tells Jimmer to not modify any other properties except
store
.
Jimmer will directly generate the following SQL:
update BOOK
set
STORE_ID = ? /* <null: long> */
where
ID = ? /* 8 */
So forget about the old inefficient pattern: query -> modify -> save