How to use joda time with JPA (eclipselink)?

喜欢而已 提交于 2019-11-27 03:16:28

问题


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.


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


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);
}



回答5:


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.




回答6:


Solution is here
joda-time-eclipselink-integration




回答7:


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.



来源:https://stackoverflow.com/questions/9783577/how-to-use-joda-time-with-jpa-eclipselink

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!