Error using Service Builder when an entity has a BLOB field
How To articles are not official guidelines or officially supported documentation. They are community-contributed content and may not always reflect the latest updates to Liferay DXP. We welcome your feedback to improve How To articles!
While we make every effort to ensure this Knowledge Base is accurate, it may not always reflect the most recent updates or official guidelines.We appreciate your understanding and encourage you to reach out with any feedback or concerns.
Legacy Article
You are viewing an article from our legacy "FastTrack"
publication program, made available for informational purposes. Articles
in this program were published without a requirement for independent
editing or verification and are provided"as is" without
guarantee.
Before using any information from this article, independently verify its
suitability for your situation and project.
Issue
- We define the following sample entity for Service Builder
<entity name="Documentos" remote-service="false" local-service="true" uuid="false" table ="REAJ_GESTION_DOCUMENTO" data-source="extDataSource">
<column name="id" type="long" db-name="ID" primary="true" id-type="sequence" id-param="REAJ_GESTION_DOCUMENTO_SEQ"/>
<column name="nombre" type="String" db-name="NOMBRE"/>
<column name="contenido" type="Blob" db-name="CONTENIDO"/>
<column name="fechaAlta" type="Date" db-name="FECHA_ALTA"/>
</entity>
- When we try to insert a new record in the entity, we get following exception:
Caused by: java.lang.NullPointerException at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer.java:521)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValue(AbstractEntityPersister.java:3868)
at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:100)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:450)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:282)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:143)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at com.liferay.portal.dao.orm.hibernate.SessionImpl.save(SessionImpl.java:252)
... 188 more
Environment
- Liferay DXP with Liferay patched Hibernate library v3.6.10
Resolution
- The correct procedure to insert a new record in an entity with a BLOB field is doing in two steps:
-
First step: Adding the fields different than BLOB type.
-
Second step: Updating the record with the BLOB field.
- A snippet for the previous entity example:
documento.setNombre(nombre);
documento.setFechaAlta(new Date());
documento = documentosLocalService.addDocumentos(documento);
documento.setContenido(contenido);
documentosLocalService.updateDocumentos(documento);
- The root cause is Service Builder framework defines an artificial 1:1 relationship between the BLOB field and the set of the rest of the fields, when using the Liferay patched Hibernate library v3.6.10.
- Please, also note that in this case, BLOB field is using the default configuration lazy="true".
- This relationship causes that Hibernate inserts the BLOB field first of all, and then the set of the rest of the fields.
- For inserting the BLOB field, a primary key is needed. But this primary key is only generated when the insertion of the rest of fields is processed.
- So, a exception is thrown because the BLOB field does not have a referenced primary key for inserting operation.
Did this article resolve your issue ?