14

I tried to use the DataTime in my entity class. Adding @Temporal(TemporalType.DATE) above the field, I got the error saying "The persistent field or property for a Temporal type must be of type java.util.Date, java.util.Calendar or java.util.GregorianCalendar". I can introduce the conversion back and forth; using setters and getters as follows:

@Temporal(TemporalType.DATE)
private Calendar attendanceDate;

public DateTime getAttendanceDate() {
    return new DateTime(this.attendanceDate);
}

public void setAttendanceDate(DateTime attendanceDate) {
    this.attendanceDate = attendanceDate.toCalendar(Locale.getDefault());
}

but I hope eclipselink to do it for me. I have gone thro' Persist Joda-time's DateTime via Hibernate. The answer suggesting to use hibernate, but I have to use eclipselink. I can use the DateTime object in my entity class with DB representation as BLOB, but I need it as Date. Is there anything like jodatime-eclipselink? Or any other suggestion? Thanks for the help.

Community
  • 1
  • 1
Ahamed
  • 39,245
  • 13
  • 40
  • 68

7 Answers7

15

Basic the link defines an EclipseLink Converter to convert from Joda DateTime to java.sql.Timestamp or Date. You could use it, or define your own converter and use it through @Convert, @Converter in EclipseLink.

For DDL creation, the converter should define the initialize method and set the type on the mapping's field to java.sql.Timestamp.

Please log a bug (or vote for the existing one) on this in EclipseLink, we should have support for Joda.

James
  • 17,965
  • 11
  • 91
  • 146
  • Regarding the DDL creation, in my initialize method I have this: mapping.getField().setSqlType(java.sql.Types.TIMESTAMP); However, the type that is created in my db is varchar(255). Any idea what the problem may be? – Catalin Morosan Oct 08 '12 at 07:09
  • 5
    @kaciula I got it to work by adding this instead: `mapping.getField().setType(java.sql.Timestamp.class);`. HTH. – Jean-Philippe Pellet Oct 17 '12 at 13:36
6

I Try use joda-time-eclipselink-integration, but don't work, problably I made something wrong,

So I made more researchs and i found this link http://jcodehelp.blogspot.com.br/2011/12/persist-joda-datetime-with-eclipselink.html, they use @Converter annotation to convert the Joda Date Time.

I Try and works for me, I hope, works for you too.

Widor
  • 13,003
  • 7
  • 42
  • 64
Hugo Prudente
  • 367
  • 4
  • 8
4

I wanted to do the same thing, and Googling around actually led me here. I was able to accomplish this using the @Access annotation. First, you annotate the class like this

@Access(AccessType.FIELD)
public class MyClass
{
    ....

This provides field access to everything so you don't have to annotate the fields individually. Then you create a getter and setter for the JPA to use.

@Column(name="my_date")
@Temporal(TemporalType.DATE)
@Access(AccessType.PROPERTY)
private Date getMyDateForDB()
{
    return myDate.toDate();
}

private void setMyDateForDB(Date myDateFromDB)
{
    myDate = new LocalDate(myDateFromDB);
}

The @Access(AccessType.PROPERTY) tells JPA to persist and retrieve through these methods.

Finally, you'll want to mark your member variable as transient as follows

@Transient
private LocalDate myDate = null;

This stops JPA from trying to persist from the field as well.

That should accomplish what you're trying to do. It worked great for me.

dnc253
  • 39,967
  • 41
  • 141
  • 157
  • How can we access `myDate` at service level (DAO)? It cannot have a mutator and an accessor (they are private as well for `myDateForDB`). – Tiny Apr 08 '14 at 05:39
  • I'm not sure I fully understand your question. You can have a public getter and setter for the `LocalDate myDate`. Since the class is annotated with `@Access(AccessType.FIELD)` JPA is not going to look at the getter and setter at all. – dnc253 Apr 08 '14 at 14:43
2

Ahamed, you mentioned it wasn't working for you. Additionally you need to override the initialize method of the converter to define the desired field type:

@Override
public void initialize(DatabaseMapping mapping, Session session) {
    ((AbstractDirectMapping) mapping)
            .setFieldClassification(java.sql.Timestamp.class);
}
marco
  • 21
  • 1
1

The following is a working example based on the answers available in the topic

Basically the easiest approach is to use EclipseLink @Converter for a DateTime field in your Entity.

The converter usage looks as follows:

import org.eclipse.persistence.annotations.Convert;
import org.eclipse.persistence.annotations.Converter;
import javax.persistence.*;
import org.joda.time.DateTime;

@Entity
public class YourEntity {

    @Converter(name = "dateTimeConverter", converterClass = your.package.to.JodaDateTimeConverter.class)
    @Convert("dateTimeConverter")
    private DateTime date;

And the converter itself:

import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
import org.joda.time.DateTime;
import java.sql.Timestamp;

public class JodaDateTimeConverter implements Converter {

    private static final long serialVersionUID = 1L;

    @Override
    public Object convertDataValueToObjectValue(Object dataValue, Session session) {
        return dataValue == null ? null : new DateTime(dataValue);
    }

    @Override
    public Object convertObjectValueToDataValue(Object objectValue, Session session) {
        return objectValue == null ? null : new Timestamp(((DateTime) objectValue).getMillis());
    }

    @Override
    public void initialize(DatabaseMapping mapping, Session session) {
         // this method can be empty if you are not creating DB from Entity classes 
         mapping.getField().setType(java.sql.Timestamp.class);
    }

    @Override
    public boolean isMutable() {
        return false;
    }

}

I am adding this for the purpose of easy copy-and-paste solution.

Atais
  • 10,857
  • 6
  • 71
  • 111
0

Answer from Atais works well. Below an upgrade to it.

You can omit @converter annotation by registering it globally. At persistance.xml in persitence-unit add:

<mapping-file>META-INF/xyz-orm.xml</mapping-file>

and file META-INF/xyz-orm.xml with content:

<?xml version="1.0"?>
<entity-mappings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm" version="2.1">
    <converter class="pl.ds.wsc.storage.converter.JodaDateTimeConverter"/>
</entity-mappings>

If your config file is META-INF/orm.xml then you can omit even first step because it is default confing for all persitence units.

Community
  • 1
  • 1
Waldemar Wosiński
  • 1,490
  • 17
  • 28
0

Solution is here
joda-time-eclipselink-integration

sinuhepop
  • 20,010
  • 17
  • 72
  • 107
Ilya
  • 29,135
  • 19
  • 110
  • 158
  • 3
    Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – oers Mar 20 '12 at 08:47
  • I found a jar file there and it has very less info. Am I supposed to use the only Converter class inside the jar file? Thanks for the help! – Ahamed Mar 20 '12 at 09:21
  • Still JPA will create a column as `BLOB` not as `DATE` :( – Ahamed Mar 20 '12 at 09:28
  • 1
    This still holds a snapshot. It does not appear to be maintained. – Tiny Jun 20 '15 at 10:49