开发者

Abstracted model interface in Play! ORM, how does initial-data.yml get loaded?

开发者 https://www.devze.com 2023-04-04 19:16 出处:网络
I have a model called Booking which has a persistent DateTime field. However I do not want to interact directly with this field, but rather through two Transient String fields, date and time. The prob

I have a model called Booking which has a persistent DateTime field. However I do not want to interact directly with this field, but rather through two Transient String fields, date and time. The problem is that I have no idea how/when play loads the data into the fields - it doesn't seem to be using the constructor I provide because the DateTime field is always null.

public class Booking extends Model {

  @Column
  @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
  public DateTime datetime;
  public Integer duration;
  @Transient
  public String date = "1970-01-01";
  @Transient
  public String time = "00:00";

  public Booking(String date, String time, Integer duration) {
    this.datetime = toDateTime(date, time);
    this.duration = duration;
  }

  public void setDate(String dateStr) {
    this.date = dateStr;
    this.datetime = toDateTime(dateStr, this.time);
  }

  public void setTime(String timeStr) {
    this.time = timeStr;
    this.datetime = toDateTime(this.date, timeStr);
  }

  public String getDate() {
    DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd");
    return this.datetime.toString(format); //NullPointerException here!
  }

  public String getTime() {
    DateTimeFormatter format = DateTimeFormat.forPattern("kk:mm");
    return this.datetime.toString(format);//NullPointerException here!
  }

here's t开发者_如何学运维he toDateTime method:

  private DateTime toDateTime(String date, String time){
    DateTimeFormatter fmt = ISODateTimeFormat.dateHourMinute();
    DateTime dt = fmt.parseDateTime(date+"T"+time);

    return dt;
  }


JPA, which play uses, uses a default empty constructor to initiate the class. In your case the Play framework (I guess) creates a Booking() constructor. JPA then uses the getters and setters to set the properties of your entity.

Perhaps you could use the @PostLoad annotation from JPA. Which causes the annotated method to be called after your persistent data is loaded into the Entity.

Update: I mentioned @PostLoad, but perhaps the @PrePersist is an better option, to check if you DateTime field is null and if this is the case you could set it with your default value. Thus like so:

@PrePersist
public void prePersist()
{
    if(this.dateTime==null)
    {
        this.dateTime = toDateTime(this.date, this.time);
    }
}


I presume DateTime is joda DateTime in the above code. I don't think JPA/Hibernate supports this data type for persistence. The ones supported are Timestamp, Calendar available as part of JDK.

You have to define a new user type in Hibernate to work with DateTime. Check this link


It appears that you can define a default constructor that takes no parameters to set up your object when JPA loads it. Like so:

public Booking() {
  DateTimeFormatter fmt = ISODateTimeFormat.dateHourMinute();
  this.datetime = fmt.parseDateTime("1970-01-01T00:00");
}

Now the only problem is that it uses the same setters I've defined when retrieving from the database: *Caused by: java.lang.IllegalArgumentException: Invalid format: "ISO8601:2011-08-25T02:00:00+0200..." *

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号