0

ENVIRONMENT

  1. Glassfish 4.0
  2. JPA - Eclipselink 2.5.0
  3. MySQL 5.5.29
  4. Trigger in MySQL to Survey table:

Trigger's code

CREATE TRIGGER `survey_BINS` 
BEFORE INSERT ON survey 
FOR EACH ROW
SET NEW.created = NOW();

PROBLEM:

  1. Insert a new survey to DB to table Survey
  2. Created field got a proper value but entity in UI is still the old one without created datetime
  3. If I sign out and refresh the page, I got the created datetime

QUESTION

  1. How to avoid this situation?
  2. Could @PrePersist notation be the answer in JPA entity?
  3. Switching cache off could help, but how is the performance then?
  4. Any idea or solution how to get updated entity after insert/update to UI?

Survey ENTITY

@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Date created;

public Date getCreated() {
    return created;
}

public void setCreated(Date created) {
    this.created = created;
}

SurveyREST-service

@Stateless
@Path("com.insame.entity.survey")
public class SurveyFacadeREST extends AbstractFacade<Survey> {
@PersistenceContext(unitName = "com.sesame_insame_war_1.0-SNAPSHOTPU")
private EntityManager em;

public SurveyFacadeREST() {
    super(Survey.class);
}

@POST
@Override
@Consumes({"application/xml", "application/json"})
public void create(Survey entity) {
    super.create(entity);
}

@PUT
@Override
@Consumes({"application/xml", "application/json"})
public void edit(Survey entity) {
    super.edit(entity);
}

AbstractFacade

public void create(T entity) {
    getEntityManager().persist(entity);
}

public void edit(T entity) {
    getEntityManager().merge(entity);
}

Thanks, Sami

Sami
  • 2,311
  • 13
  • 46
  • 80
  • Could you provide more code to show how you are persisting the survey entity? Also, the interface between the UI and the persistence tier? – JamesB Aug 21 '13 at 07:29
  • I added some code, I hope it helps you and then me :) – Sami Aug 21 '13 at 08:08
  • I could be totally wrong, (say, if you are in a case [trigger for changing the primary key](https://stackoverflow.com/a/12307512/9549068)) : when you are trying to access to a `entity`, and a `query` from `entityManager` is giving you an outdate object value (/ not accessing from the database), maybe `entityManager.clear()` can help you? (for others that are also looking for an answer) – Nor.Z Mar 09 '22 at 07:45

2 Answers2

2
  1. To avoid this situation you need to set the field not in database but in java. Because when you save entity it is being inserted into the cache. To get values that were updated in database you need to refresh the entity.

  2. Yes this annotation could help you to solve the problem. @PrePersist and @PreUpdate or implementing onSave(Object[] state, String[] propertyNames, Type[] types) or onUpdate with same arguments

  3. If you use second level cache and you will switch it off you can loose performance but also it can happen that you will not notice anything. Hibernate 2nd level cache is usually not giving a lot of performance improvement. Better use caching on higher level of abstraction. Such cache can give more performance improvement. But again you will not be able to use database data updates.

  4. Use the solution from option number 2: @PrePersist and @PreUpdate.

From my personal experience I would not recommend you to use data updates with the help of triggers. For me they were slowing down database dramatically. Also If you use database triggers or stored proc it is less scalable than using java for it. And also it is difficult to use with caching, because you want to expire necessary cache regions on some data updates.

trims
  • 453
  • 4
  • 9
  • I took the trigger off and tried to use PrePersist. I got the exception when using it: Internal Exception: Exception [EclipseLink-7228] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.ValidationException Exception Description: The Callback method [setCreated] on the listener class [class com.insame.entity.Survey] has an incorrect signature. It should not have any parameters.. Please see server.log for more details. @PrePersist public void setCreated(Date created) { this.created = new Date(); } – Sami Aug 21 '13 at 08:44
  • Oh. You are using it not the way you should. PrePersist method should not have any paramaters. You create speaprate method that will be called before persisting the entity. There you put the logic from you trigger. – trims Aug 21 '13 at 10:15
  • Now it is working but in UI i have milliseconds: 1377088415000 and in DB I've got: '2013-08-21 15:36:46' – Sami Aug 21 '13 at 12:39
  • I think that by default spring converts date object to milliseconds when marshalling objects to xml or json. If you want some other format you should specify how to convert the Date when marshalling your entity to xml or json. But this is out of scope of this question. – trims Aug 21 '13 at 14:21
  • I managed this one with moment.js. Evertything is working now so thanks for everyone! – Sami Aug 21 '13 at 15:09
1

If you want to use triggers to assign fields on insert, check out EclipseLink's returningPolicy which can be used to retrieve the value after the insert. See http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_returninsert.htm#CIHHEGJE for the annotation description

Chris
  • 20,138
  • 2
  • 29
  • 43
  • If I understood correctly this is working only with Oracle DB? Nice to know BTW. I might test this one if this is working with MySQL? – Sami Aug 21 '13 at 15:13