0

I have an object which need to be updated, the following form is used to update it. I have an attribute called createDate that I do not want to be changed when I update the record therefore I did not include it in the form, but when I submit the form it changes the value of createDate to null.

<s:form method="POST" autocomplete="on" action="update">
    <input type="hidden" name="user.id" value="${user.id}"/>
   ....
</s:form>

Code

final Session session = HibernateUtil.getSession();
try {
    final Transaction tx = session.beginTransaction();
    try {
        session.update(user);
        if (!tx.wasCommitted()) {    
            tx.commit();
        }
        return "SUCCESS";
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
        return "Failed";
    }
} finally {
    HibernateUtil.closeSession();
}

User class

....
@Column(name = "createdate")
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getCreateDate() {
    return createDate;
}

public void setCreateDate(Date createDate) {
    this.createDate = createDate;
}

I supposed it changes the value to null because the field has not been included in the form so I added the following code to my form, although the HTML source of the page show the correct value of createDate but when I submit the form it throws following exception.

<input type="hidden" name="user.createDate" value="${user.createDate}"/>

Exception after adding input hidden for createDate

INFO:   2014-02-26 12:37:25,896 -  WARN [CommonsLogger.java:60] ognl.MethodFailedException: Method "setCreateDate" failed for object com.myproject.myclasses.User@2d680c36 [java.lang.NoSuchMethodException: com.myproject.myclasses.User.setCreateDate([Ljava.lang.String;)]
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1305)
    at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:1494)
    at ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:85)
    at ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:162)
    at com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:27)
        ......
Trein
  • 3,658
  • 27
  • 36
AlexCartio1
  • 238
  • 3
  • 9
  • 29

1 Answers1

2

The problem you are facing seems to be related with argument that setCreateDate() is expecting. Since your method is declared as setCreateDate(Date) it is not compatible with setCreateDate(String), which is expected to be called when you submit the form.

In order to update the current model object, you will have to retrieve it from DB using the submitted Id, update the pertinent fields and then call session.update(). You code will look like

public void updateUserInfo(User user) {
    Session s = getSession();
    Transaction t = s.beginTransaction();
    User u = (User) s.load(User.class, user.getId());
    u.setAddress(user.getAddress());
    u.setEmail(user.getEmail());
    s.update(u);
    t.commit();
    closeSession();
}

More informations about Hibernate listeners to update fields just before persisting an entity. If you want to set the createDate field just before your record is persisted, you can use

@PrePersist
protected void onCreate() {
    createDate = new Date();
}

The methods annotated with @PrePersist and @PreUpdate are called just before Hibernate persist the entity for the first time or update it, respectively. You can get more information here.

EDIT: I've notice you are using the Session API of Hibernate. In this case, the suggestion above won't work. In order to get it working with your current implementation, you should use the Hibernate events API.

First, create an interface for objects that have to be updated just before it will be persisted (something like this)

public interface Dateable {

    void setCreateDate(Date date);
}

Modify your User class to implement that interface.

public class User implements Dateable {
   //...
}

Then create a Listener that listens for the SaveOrUpdateEvent on Dateable entities and modifies the create property:

import org.hibernate.event.SaveOrUpdateEvent;
import org.hibernate.event.def.DefaultSaveOrUpdateEventListener;

public class SaveOrUpdateDateListener extends DefaultSaveOrUpdateEventListener {

    @Override
    public void onSaveOrUpdate(SaveOrUpdateEvent event) {
        if (event.getObject() instanceof Dateable) {
            Dateable record = (Dateable) event.getObject();
            record.setCreateDate(new Date());
        }
        super.onSaveOrUpdate(event);
    }
}

Finally, configure the above listener via hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
      .....       
        <event type="save-update">
            <listener class="SaveOrUpdateDateListener"/>
        </event>
    </session-factory>
</hibernate-configuration>
Trein
  • 3,658
  • 27
  • 36
  • I've update the answer whit more detail about the JPA annotations. – Trein Feb 26 '14 at 02:01
  • I am using hibernate does this code work with hibernate? is there any other method to do it ? should I retrieve the createDate and put it into new object before being persisted? – AlexCartio1 Feb 26 '14 at 02:04
  • Yes, it does. Hibernate implements JPA specification. You can get an instance of `Date` from somewhere else and assign it to `createDate` or create a new instance (as in the example). – Trein Feb 26 '14 at 02:07
  • all right, how about if I retrieve the value of createDate from DB and put it into the new object's createDate and then update the new object session.update(user); in this case correct value will be overridden on the createDate field on DB. As the problem is that, currently everytime I try to update the record it is overridding the value of createDate by Null. – AlexCartio1 Feb 26 '14 at 02:11
  • I apologize for the misleading information. The `@PrePersist` annotation will only work if you use Hibernate via `JPA`. As you are using `Session API`, you should follow the steps above to register a listener that will do what `@PrePersist` does. Concerning your question about `createDate` being overridden, is this `Date` retrieved from DB different than `null`? – Trein Feb 26 '14 at 02:30
  • Lets say the value in DB is 2014-1-1 when I retrieve the record and then submit the form, as I do not include the value of createDate hibernate replace its value with Null, (after updating the value of createDate will be Null). I am asking how about if I retrieve its value (2014-1-1) from DB then put it into the object's createDate variable before updating the object? – AlexCartio1 Feb 26 '14 at 02:42
  • I'm afraid that, in your case, you will have to retrieve the entity from DB using the submitted ID, update only the pertinent fields and then call `session.update()`. – Trein Feb 26 '14 at 02:51
  • I've just update the answer with a snippet of what it will look like. – Trein Feb 26 '14 at 02:59