2012-03-20 15 views
14

Próbowałem użyć DataTime w mojej klasie entity. Dodając @Temporal(TemporalType.DATE) powyżej pola, otrzymałem komunikat o błędzie z informacją, że "Trwałe pole lub właściwość typu Temporal musi być typu java.util.Date, java.util.Calendar lub java.util.GregorianCalendar". Mogę wprowadzić konwersację tam iz powrotem; za pomocą ustawiające i pobierające następująco:Jak używać czasu joda z JPA (eclipselink)?

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

ale mam nadzieję eclipselink zrobić to za mnie. Poszedłem thro 'Persist Joda-time's DateTime via Hibernate. Odpowiedź sugeruje użycie hibernacji, ale muszę użyć eclipselink. Mogę użyć obiektu DateTime w mojej klasie encji z reprezentacją DB jako BLOB, ale potrzebuję go jako Date. Czy jest coś takiego jak jodatime-eclipselink? Lub jakiejkolwiek innej sugestii? Dzięki za pomoc.

Odpowiedz

15

Podstawowe link definiuje EclipseLink Converter przekonwertować z Joda DateTime do java.sql.Timestamp lub daty. Można go użyć lub zdefiniować własny konwerter i używać go przez @Convert, @Converter w EclipseLink.

Do tworzenia DDL konwerter powinien zdefiniować metodę initialize i ustawić typ w polu mapowania na java.sql.Timestamp.

Proszę zgłoś błąd (lub zagłosuj na istniejący) na ten temat w EclipseLink, powinniśmy mieć wsparcie dla Jody.

+0

Odnośnie tworzenia DDL, w mojej metodzie inicjowania mam to: mapping.getField() .setSqlType (java.sql.Types.TIMESTAMP); Jednak typ, który jest tworzony w mojej db jest varchar (255) .Dowolny pomysł, co może być problem? –

+5

@kaciula Mam go do pracy, dodając to zamiast : 'mapping.getField(). setType (java.sql.Timestamp.class);'. HTH. –

0

Rozwiązanie jest tutaj
joda-time-eclipselink-integration

+3

Chociaż może to teoretycznie odpowiedzieć na pytanie, [byłoby wskazane] (http://meta.stackexchange.com/q/8259), aby uwzględnić istotne części odpowiedzi tutaj, i podać link do odniesienia. – oers

+0

Znalazłem plik jar i ma on bardzo mniej informacji. Czy mam używać tylko klasy Konwertera wewnątrz pliku JAR? Dzięki za pomoc! – Ahamed

+0

Nadal JPA utworzy kolumnę jako 'BLOB', a nie jako' DATA' :( – Ahamed

2

Zawstydzony, wspomniałeś, że to nie działa dla ciebie. Dodatkowo trzeba przesłonić metody initialize konwertera, aby określić żądany typ pola:

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

chciałem zrobić to samo, a Googling wokół rzeczywiście doprowadziło mnie tutaj. Udało mi się to osiągnąć za pomocą adnotacji @Access. Po pierwsze, opisywanie klasy jak ten

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

To pole umożliwia dostęp do wszystkiego, więc nie trzeba opisywać indywidualnie pola. Następnie tworzysz getter i ustawiający dla WZP do użycia.

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

Numer @Access(AccessType.PROPERTY) informuje JPA, aby kontynuował i odzyskiwał te metody.

Wreszcie, będziemy chcieli, aby zaznaczyć swoją zmienną składową jako przemijające następująco

@Transient 
private LocalDate myDate = null; 

Zatrzymuje JPA z starają się utrzymywać z pola, jak również.

To powinno doprowadzić do tego, co próbujesz zrobić. Udało się to dla mnie świetne.

+0

Jak uzyskać dostęp do 'myDate' na poziomie usługi (DAO)? Nie może mieć mutatora i akcesora (są prywatne jak również dla 'myDateForDB').) – Tiny

+0

Nie jestem pewien, czy w pełni rozumiem twoje pytanie.Możesz mieć publicznego gettera i ustawiającego dla' LocalDate myDate' .Od tej klasy jest adnotacji z '@ Access (AccessType.FIELD)' JPA nie zamierza w ogóle patrzeć na zdobywcę i setera . – dnc253

6

ja próbie użycia Joda-time-EclipseLink-integracji, ale nie działa, problably zrobiłem coś źle,

Więc zrobiłem więcej Researchs i znalazłem ten link http://jcodehelp.blogspot.com.br/2011/12/persist-joda-datetime-with-eclipselink.html, używają @Converter adnotacji do konwersji Czas Data Joda.

Próbuję i pracuje dla mnie, mam nadzieję, działa również dla Ciebie.

+1

+1: Ten link wyjaśnia to z wielką szczegółowością :) –

1

Poniżej znajduje się przykład działa na podstawie odpowiedzi dostępnych w temacie

Zasadniczo najprostszym sposobem jest użycie EclipseLink @Converter dla DateTime pola w swojej jednostce.

Zastosowanie konwertera wygląda następująco:

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; 

A sam konwerter:

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

} 

dodaję to w celu łatwego kopiowania i wklejania rozwiązania.

0

Odpowiedź od Atais Odpowiedź jest dobra. Poniżej aktualizacji do niego.

Możesz pominąć adnotację @converter rejestrując ją globalnie. Na persistance.xml w persitence jednostce dodać:

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

i złożyć META-INF/xyz-orm.xml z treścią:

<?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> 

Jeśli plik konfiguracyjny jest META-INF/orm.xml wtedy można pominąć nawet pierwszy krok, ponieważ jest domyślny dla confing wszystkie jednostki persytencji.

Powiązane problemy