簡體   English   中英

playframework:在播放中將java8 java.time類型LocalDate與冬眠保持一致

[英]playframework: persist java8 java.time type LocalDate with hibernate in Play

我無法為新的java.time。*類型進行任何類型的轉換或兼容性。 或至少是LocalDate。

我看到例外:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[IllegalStateException: Error(s) binding form: {"dateOfBirth":["Invalid value"]}]]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:265) ~[play_2.11-2.4.4.jar:2.4.4]

Caused by: java.lang.IllegalStateException: Error(s) binding form: {"dateOfBirth":["Invalid value"]}
    at play.data.Form.get(Form.java:592) ~[play-java_2.11-2.4.4.jar:2.4.4]
    at controllers.Application.addPatient(Application.java:49) ~[classes/:na]

我發現有幾種方法,原則上應該可以使JPA休眠,但是,如果這又是Play的問題,還是什么? 我不確定。

第一種方法:

提供您自己的自定義轉換器:

@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> 
{
    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
        return (locDate == null ? null : Date.valueOf(locDate));
    }

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

然后,在現場需要使用此功能:

@Convert(converter = LocalDateAttributeConverter.class)
public LocalDate dateOfBirth;

http://www.thoughts-on-java.org/persist-localdate-localdatetime-jpa/

當然,據我所知,原則上,我不需要@Convert注釋,因為轉換器本身是使用@Converter(autoApply = true)注釋進行注釋的。 但是,因為我找不到關於成功使用Play Converters的文檔(也沒有Google上的任何點擊),因此我嘗試了使用和不使用轉化器都沒有成功。

下一個方法:

好吧,據我所知,從休眠5開始,現在應該支持較新的java8類型。...並且我已經使用了5.0.5,並且在類路徑中包括了必要的庫:

"org.hibernate" % "hibernate-java8" % "5.0.5.Final", 

https://hibernate.atlassian.net/browse/HHH-8844

那根本沒有幫助。 相同的堆棧跟蹤。

為了達到良好的效果,我添加了休眠特定注釋

@Type(type="java.time.LocalDate")

到我的領域。

那將是丑陋的。 但是,如果它有所幫助,我會忍受的。 沒有。 同樣的例外。 與轉換器一起使用會引起其他錯誤。 這很有趣。

我在Hibernate 5.0.5中使用Play 2.4。 有沒有人設法做到這一點?

好的,所以我終於知道了。 我應該更仔細地(慢慢地)看一下堆棧跟蹤。

實際上,我最終受到三個問題的影響。 全部以三種不同方式解決。 但是,所有這些都與對較新的java.time類的“掛起”支持有關。 公平地說,底層庫的支持只是最近才引入的。

第一個問題:表單綁定驗證失敗。

我在控制器中調試了表單綁定工作:

    Form<Patient> form = Form.form(Patient.class);
    form = form.bindFromRequest();
    System.out.println(form.toString());
    Patient patient = form.get();

雖然在調用form.get()引起了form.get() ,但實際上在調用form.bindFromRequest()已經發生了錯誤。 錯誤已在Form.errors映射中注冊,該映射來自org.springframework.validation.DataBinder

谷歌搜索進一步,我碰到了這個:

https://groups.google.com/forum/#!topic/play-framework/Wl_ip56111c

實施解決了我的第一個問題,然后進行了表單綁定。

第二個問題:持久性

我正在使用Hibernate來保持對象的持久性。 將hibernate-java8添加到我的類路徑中可啟用新數據類型的持久性。 對於播放2,這將放入您的build.sbt文件中。

libraryDependencies ++= Seq(
  javaJdbc,
  cache,
  javaWs,
  javaJpa,
  "org.hibernate" % "hibernate-entitymanager" % "5.0.5.Final",
  "org.hibernate" % "hibernate-java8" % "5.0.5.Final", 
)

https://hibernate.atlassian.net/browse/HHH-8844

第三個問題:Json支持

我無法將模型實例化呈現為Json對象。 應該支持它,但是在某種程度上,它不是安裝程序。

我發現這篇文章向我展示了如何解決:

    // http://stackoverflow.com/questions/32872474/how-to-use-java-time-localdate-on-a-play-framework-json-rest/32891177#comment56814598_32891177
    // https://groups.google.com/forum/?hl=en.#!searchin/play-framework/java.time.localdate/play-framework/Dv-IpvBqWgo/l6NTp3e0BQAJ

為了方便起見,我在此處發布了此修復程序:

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new Jdk8Module());
    mapper.registerModule(new JSR310Module());
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    Json.setObjectMapper(mapper);

在應用程序啟動時需要執行第一和第三修復程序。 對於游戲2.4,GlobalSettings對象已被棄用,因此我不確定他們希望您如何進行這種初始化(有人嗎?)。 但是,幸運的是它仍然可以工作。 我當然沒有Globals類(默認情況下不再創建),所以我創建了該類,並使用以下鍵(通過application.conf文件)將我的應用指向該類:

# Minimal global settings to fix form binding and json support of java.time.LocalDate
application.global=GlobalFixes

為了方便起見,我將整個課程發布在這里,供那些仍在學習Playframework方式的人使用

import play.*;
import play.data.format.Formatters;
import play.libs.Json;

import java.time.LocalDate;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;

import java.text.ParseException;

/**
 * Fixes for play application. TODO remove this once Play has fixed support for LocalDate
 * @author Sean van Buggenum
 *
 */
public class GlobalFixes extends GlobalSettings
{   // One can see from the javadoc of java.time.LocalDate that the toString guarantees this format, regardless of locale!
    private static final Pattern datePattern = Pattern.compile("(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)");

    public void onStart(Application app)
    {
        //https://groups.google.com/forum/#!topic/play-framework/Wl_ip56111c
        Formatters.register(LocalDate.class, new Formatters.SimpleFormatter<LocalDate>()
        {
            @Override
            public LocalDate parse(String input, Locale l) throws ParseException
            {
                Matcher m = datePattern.matcher(input);
                if (!m.matches())
                    throw new ParseException("No valid Input for date text: " + input, 0);
                return LocalDate.of(Integer.valueOf(m.group(1)), Integer.valueOf(m.group(2)), Integer.valueOf(m.group(3)));
            }

            @Override
            public String print(LocalDate localTime, Locale l)
            {
                return localTime.toString();
            }
        });

        // Add Json's java 8 support
        // http://stackoverflow.com/questions/32872474/how-to-use-java-time-localdate-on-a-play-framework-json-rest/32891177#comment56814598_32891177
        // https://groups.google.com/forum/?hl=en.#!searchin/play-framework/java.time.localdate/play-framework/Dv-IpvBqWgo/l6NTp3e0BQAJ
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jdk8Module());
        mapper.registerModule(new JSR310Module());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        Json.setObjectMapper(mapper);
    }
}

我希望這可以幫助一些人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM