Hibernate version: Hibernate-3.2 RC2
Name and version of the database : MySQL 5.0.24
Hi. I've got a Customer entity with a date of birth (TemporalType.DATE) and I calculate his age in a PostLoad method (stored in a transient attribut). I've copied paste this code from Hibernate EntityManager doc (ยง5.3 - calculateAge() method). Here is the code (simplified with no getters/setters) :
Code:
@Entity
@Table(name = "t_customer")
public class Customer extends Person {
private String telephone;
private String email;
@Column(name = "date_of_birth")
@Temporal(TemporalType.DATE)
private Date dateOfBirth;
@Transient
private Integer age;
@OneToOne(fetch = FetchType.LAZY, optional = true, cascade = CascadeType.ALL)
@JoinColumn(name = "address_fk")
private Address homeAddress;
@PostLoad
public void calculateAge() {
if (dateOfBirth == null) {
age = -1;
return;
}
Calendar birth = new GregorianCalendar();
birth.setTime(dateOfBirth);
Calendar now = new GregorianCalendar();
now.setTime(new Date());
int adjust = 0;
if (now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR) < 0) {
adjust = -1;
}
age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) + adjust;
}
I wrote a test class that sets a birth date and makes sure that the age is set. This class creates a customer, finds it and checks that the age is not null. This fails except if you refresh the customer after the find :
Code:
// previously set some default values to customer
// persist the customer entity
tx.begin();
em.persist(customer);
tx.commit();
Long id = customer.getId();
// Finds the created customer
tx.begin();
customer = em.find(Customer.class, id);
// without the call to the refresh method, age is null
em.refresh(customer);
tx.commit();
For me PostLoad should be called after the find. The spec doesn't say much and the following sentence is ambiguous I find. In one hand the method is called
"after the entity has been loaded into the current persistence context" but on the other hand PostLoad is
"invoked before a query result is returned" (does it mean before the find?) :
The PostLoad method for an entity is invoked after the entity has been loaded into the current persistence context from the database or after the refresh operation has been applied to it. The PostLoad method is invoked before a query result is returned or accessed or before an association is traversed.
So, is it normal to call refresh to have the PostLoad working or should it be called after the find ?
Thanks,
Antonio