How to use the Java 8 LocalDateTime with JPA and Hibernate

后端 未结 5 1185
鱼传尺愫
鱼传尺愫 2020-11-27 18:22

I have the following class description snippet:

... 
@Column(name = \"invalidate_token_date\")
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime inv         


        
5条回答
  •  余生分开走
    2020-11-27 19:22

    Since Hibernate 4 doesn't support it you need to implement a user type as shown in this example.

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

    The new usertype can then be used in the mapping with the @Type annotation. For e.g.

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

    The @Type annotation needs a full path to the class that implements the userType interface; this is the factory for producing the target type of the mapped column.

    Here's how to do the same thing in JPA2.1

提交回复
热议问题