Skip to main content

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 its store 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:

JPA Example
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

sqlClient.update(
Immutables.createBook(draft -> {
draft.setId(8L);
draft.setStore(null);
})
);
  • Explicitly use update (or save(book, SaveMode.UPDATE_ONLY)) to indicate this is an update operation, avoiding the probing query of the UPSERT mode to simplify the discussion.

  • Make up a Book object out of thin air, only assigning its id property and store 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 */
info

So forget about the old inefficient pattern: query -> modify -> save