2015-01-02 6 views
15

を休止:@TemporalLocalDateTime.をサポートしていないので、私はジョダからのLocalDateTimeを使用する方法の提案を見たのJava 8のLocalDateTimeと私は以下のクラス記述の抜粋を持っている4

... 
@Column(name = "invalidate_token_date") 
@Temporal(TemporalType.TIMESTAMP) 
private LocalDateTime invalidateTokenDate; 
.... 

このコードは動作しません。 -Timeですが、Java 8を使用しています。

アドバイスをお願いします。


P.S.ここで
私の現在のJPAの依存関係です:

<dependency> 
    <groupId>javax.persistence</groupId> 
    <artifactId>persistence-api</artifactId> 
    <version>1.0</version> 
</dependency> 

答えて

19

Hibernateはあなたがthis例に示すように、ユーザタイプを実装する必要があり、それをサポートしていませんので。

import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.type.StandardBasicTypes; 
import org.hibernate.usertype.EnhancedUserType; 

import java.io.Serializable; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.time.Instant; 
import java.time.LocalDateTime; 
import java.time.ZoneId; 
import java.util.Date; 

public class LocalDateTimeUserType implements EnhancedUserType, Serializable { 

    private static final int[] SQL_TYPES = new int[]{Types.TIMESTAMP}; 

    @Override 
    public int[] sqlTypes() { 
     return SQL_TYPES; 
    } 

    @Override 
    public Class returnedClass() { 
     return LocalDateTime.class; 
    } 

    @Override 
    public boolean equals(Object x, Object y) throws HibernateException { 
     if (x == y) { 
      return true; 
     } 
     if (x == null || y == null) { 
      return false; 
     } 
     LocalDateTime dtx = (LocalDateTime) x; 
     LocalDateTime dty = (LocalDateTime) y; 
     return dtx.equals(dty); 
    } 

    @Override 
    public int hashCode(Object object) throws HibernateException { 
     return object.hashCode(); 
    } 


    @Override 
    public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner) 
      throws HibernateException, SQLException { 
     Object timestamp = StandardBasicTypes.TIMESTAMP.nullSafeGet(resultSet, names, session, owner); 
     if (timestamp == null) { 
      return null; 
     } 
     Date ts = (Date) timestamp; 
     Instant instant = Instant.ofEpochMilli(ts.getTime()); 
     return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); 
    } 

    @Override 
    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SessionImplementor session) 
      throws HibernateException, SQLException { 
     if (value == null) { 
      StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, null, index, session); 
     } else { 
      LocalDateTime ldt = ((LocalDateTime) value); 
      Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant(); 
      Date timestamp = Date.from(instant); 
      StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, timestamp, index, session); 
     } 
    } 

    @Override 
    public Object deepCopy(Object value) throws HibernateException { 
     return value; 
    } 

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

    @Override 
    public Serializable disassemble(Object value) throws HibernateException { 
     return (Serializable) value; 
    } 

    @Override 
    public Object assemble(Serializable cached, Object value) throws HibernateException { 
     return cached; 
    } 

    @Override 
    public Object replace(Object original, Object target, Object owner) throws HibernateException { 
     return original; 
    } 

    @Override 
    public String objectToSQLString(Object object) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public String toXMLString(Object object) { 
     return object.toString(); 
    } 

    @Override 
    public Object fromXMLString(String string) { 
     return LocalDateTime.parse(string); 
    } 

} 

新しいユーザータイプは、@Typeアノテーションを使ったマッピングで使用できます。例えば、

@Type(type="com.hibernate.samples.type.LocalDateTimeUserType") 
@Column(name = "invalidate_token_date") 
private LocalDateTime invalidateTokenDate; 

@Typeアノテーションには、userTypeインターフェイスを実装するクラスへのフルパスが必要です。これは、マップされた列のターゲット型を生成するためのファクトリです。あなたは、Java EE 7を使用できる場合JPA2.1

+0

あなたのクラスを追加した後、マッピングをどのように変更する必要がありますか? – gstackoverflow

+0

答えを使用情報 –

+0

で更新しました。これを 'java.util.LocalDate'フィールドを格納するように変換すると、例外をスローするので、' java.sql.Date.toInstant() 'メソッドを経由することはできません。代わりに 'toLocalDate'を使用してください。 – Gwaptiva

9

で同じことを行う方法

Here'ssolutionよりエレガントあり:

>>この実装:

@Converter(autoApply = true) 
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Date> { 

    @Override 
    public Date convertToDatabaseColumn(LocalDateTime date) { 
     if (date == null){ 
      return null; 
     } 
     return date.toDate(); 
    } 

    @Override 
    public LocalDateTime convertToEntityAttribute(Date value) { 
     if (value == null) { 
      return null; 
     } 
     return LocalDateTime.fromDateFields(value); 
    } 
} 

を> >次のように使用してください:

... 
@Column(name = "invalidate_token_date") 
private LocalDateTime invalidateTokenDate; 
.... 

(autoApply = true)は、@ConverterがJPAエンティティのすべてのLocalDateTimeプロパティの変換に自動的に使用されることを意味します。

Btw、AttributeConverterもEnumをマッピングするのにはかなり良いです。

+0

どのライブラリからlocalDateTime toDateメソッドとfromDateFieldsメソッドが得られますか? – obesechicken13

+0

ここにコンバーターがあります:http://stackoverflow.com/questions/19431234/converting-between-java-time-localdatetime-and-java-util-date – obesechicken13

+1

これは実際にJPAの機能です。これはSpring Data JPAでも動作しますが、 Java EEだけでなく、 –

0

私はjava.time。*クラスを使用できるように単純なプラグインを作成しました。現時点で最も一般的に使用されるクラスが実装されています。ここをクリックしてください:https://github.com/garcia-jj/jpa-javatimeプロジェクトページで使用する方法の詳細があります

<dependency> 
    <groupId>br.com.otavio</groupId> 
    <artifactId>jpa-javatime</artifactId> 
    <version>0.2</version> 
</dependency> 

あなたはMavenを使用している場合は、これはアーティファクトの構成です。

ありがとうございます。どんなHibernateの5.xのユーザーの場合

35

、あなたは何もする必要はありません

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-java8</artifactId> 
    <version>5.0.0.Final</version> 
</dependency> 

があります。依存関係を追加するだけで、Java 8の時間型は他の基本型と同様に動作し、注釈は必要ありません。

private LocalDateTime invalidateTokenDate; 

注:これはtimestampタイプに保存されません。 MySQLでテストすると、datetimeタイプに保存されます。

+1

私の夜に保存されました:)ありがとう –

+0

これは、春の設定には不十分です。プロジェクトへのhibernate-java8依存性を追加した後も、ClassCastExceptionが発生します。 –

+1

ありがとうございます。 Spring 4.2.5とHibernate 5.1.31で、hibernate-java8 artifactを追加してくれました。 org.hibernate.type.SerializationExceptionを取得していました:LocalDateTimeフィールドを持つエンティティを逆シリアル化できませんでした。 –

関連する問題