2015-04-16 22 views
1

我有一個spring-boot 1.2.1應用程序,使用Liquibase來管理我的數據庫。我也用hibernate的Spring-data-jpa。我有一個表:Java LocalDateTime和db之間的正確映射

<createTable tableName="ADDRESS"> 
    <column name="address_id" type="bigint" autoIncrement="true"> 
     <constraints primaryKey="true" nullable="false"/> 
    </column> 
    <column name="address_line1" type="varchar(500)"/> 
    <column name="address_line2" type="varchar(500)"/> 
    <column name="address_line3" type="varchar(500)"/> 
    <column name="city" type="varchar(500)"/> 
    <column name="state" type="varchar(50)"/> 
    <column name="zip" type="varchar(50)"/> 
    <column name="status" type="varchar(100)"/> 
    <column name="address_type" type="varchar(100)"/> 
    <column name="begin_date_time" type="DATETIME"/> 
    <column name="end_date_time" type="DATETIME"/> 
</createTable> 

和實體:

@Entity 
@Table(name = "ADDRESS") 
public class Address { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long addressId; 
    private String addressLine1; 
    private String addressLine2; 
    private String addressLine3; 
    private String city; 
    private String state; 
    private String zip; 

    @Enumerated(EnumType.STRING) 
    private Status status; 

    @Enumerated(EnumType.STRING) 
    private AddressType addressType; 

    private LocalDateTime beginDateTime; 
    private LocalDateTime endDateTime; 
    // getters & setters 

當我嘗試使用此表:

Address officeAddress = new Address(); 
officeAddress.setAddressLine1("123 Somewhere Lane"); 
officeAddress.setAddressLine2("Suite 100"); 
officeAddress.setAddressLine3("line 3"); 
officeAddress.setCity("Glenwood Springs"); 
officeAddress.setState("CO"); 
officeAddress.setZip("12345-789"); 
officeAddress.setAddressType(AddressType.OFFICE); 
officeAddress.setStatus(Status.ACTIVE); 
officeAddress.setBeginDateTime(LocalDateTime.of(2014, 8, 26, 12, 01)); 

return addressRepository.save(officeAddress); 

我得到一個異常:

015-04-16 08:12:17.351 WARN 13866 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 22007, SQLState: 22007 
2015-04-16 08:12:17.352 ERROR 13866 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot parse "TIMESTAMP" constant "aced00057372000d6a6176612e74696d652e536572955d84ba1b2248b20c00007870770905000007de081a0cfe78"; SQL statement: 
insert into address (address_id, address_line1, address_line2, address_line3, address_type, begin_date_time, city, end_date_time, state, status, zip) values (null, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) -- (NULL, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10) [22007-172] 
2015-04-16 08:12:19.377 WARN 13866 --- [ Test worker] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt 

我對H2(測試)和PostgreSQL(d eployment)。我認爲Liquibase docs表明這是聲明表列的方式,但顯然有些問題是錯誤的。我確實需要日期&時間,但不確定是否需要時區信息。

有沒有人知道這適當的映射?

+2

這取決於您使用JPA實現。對於一般的解決方案,您可以在jpa 2.1+中使用[轉換器](https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa) 。如果你使用hibernate,你可能會對[hibernate-java8](https://hibernate.atlassian.net/browse/HHH-8844)模塊感興趣。 – pozs

+0

看起來像hibernate 5之前的版本不支持所有Java 8時間功能。我使用Hibernate 4.3.4.Final,並且不願意將它與Hibernate 5.0.0.Beta1交換。 – sonoerin

+0

好吧,我爲Date,Time和DateTime創建了轉換器,並用實體註釋了實體中的每一列。顯然這是Hibernate 5發佈之前的解決方案。 – sonoerin

回答

4

您可以使用轉換器:

import javax.persistence.AttributeConverter; 
import javax.persistence.Converter; 
import java.sql.Timestamp; 
import java.time.LocalDateTime; 

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

    @Override 
    public Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) { 
    return localDateTime != null ? Timestamp.valueOf(localDateTime) : null; 
    } 

    @Override 
    public LocalDateTime convertToEntityAttribute(Timestamp timestamp) { 
    return timestamp != null ? timestamp.toLocalDateTime() : null; 
    } 
} 

和:

import javax.persistence.AttributeConverter; 
import javax.persistence.Converter; 
import java.sql.Date; 
import java.time.LocalDate; 

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

    @Override 
    public Date convertToDatabaseColumn(LocalDate localDate) { 
     return localDate != null ? Date.valueOf(localDate) : null; 
    } 

    @Override 
    public LocalDate convertToEntityAttribute(Date date) { 
     return date != null ? date.toLocalDate() : null; 
    } 
}