日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

在JPA 2.1中使用@Convert正确完成映射枚举

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在JPA 2.1中使用@Convert正确完成映射枚举 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果您曾經在JPA中使用過Java枚舉,那么您肯定會意識到它們的局限性和陷阱。 使用enum作為@Entity的屬性通常是一個很好的選擇,但是2.1之前的JPA不能很好地處理它們。 它給了您2 + 1個選擇:

托肖夫達林

  • @Enumerated(EnumType.ORDINAL) (默認值)將使用Enum.ordinal()映射enum值。 基本上,第一個枚舉值將在數據庫列中映射為0 ,第二個映射為1 ,依此類推。這非常緊湊,并且在要修改枚舉時非常有用。 在中間刪除或增加值或重新排列它們將完全破壞現有記錄。 哎喲! 更糟糕的是,單元測試和集成測試通常在干凈的數據庫上運行,因此它們不會發現舊數據之間的差異。
  • @Enumerated(EnumType.STRING)更安全,因為它存儲enum字符串表示形式。 現在,您可以安全地添加新值并移動它們。 但是,重命名Java代碼中的enum仍會破壞DB中的現有記錄。 更重要的是,這種表示非常冗長,不必要地消耗了數據庫資源。
  • 您還可以使用原始表示形式(例如single char或int ),并在@PostLoad / @PrePersist / @PreUpdate事件中手動來回映射它。 從數據庫角度來看,最靈活,最安全,但是很丑陋。
  • 幸運的是,幾天前發布的Java Persistence API 2.1 ( JSR-388 )提供了可插拔數據轉換器的標準化機制。 這樣的API以專有形式存在很久了,它并不是真正的火箭科學,但是將其作為JPA的一部分是一個很大的改進。 據我所知, Eclipselink是迄今為止唯一可用的JPA 2.1實現,因此我們將使用它進行一些實驗。

    我們將從作為“ 窮人的CRUD:jqGrid,REST,AJAX和Spring MVC一屋子 ”的一部分開發的示例Spring應用程序開始。 該版本沒有持久性,因此我們將在由Eclipselink支持的Spring Data JPA之上添加薄DAO層。 到目前為止,只有實體是Book :

    @Entity public class Book {@Id@GeneratedValue(strategy = IDENTITY)private Integer id;//...private Cover cover;//... }

    其中Cover是enum :

    public enum Cover {PAPERBACK, HARDCOVER, DUST_JACKET}

    ORDINAL和STRING都不是一個很好的選擇。 前者是因為以任何方式重新排列前三個值都會破壞現有記錄的加載。 后者太冗長。 這是JPA中的自定義轉換器起作用的地方:

    import javax.persistence.AttributeConverter; import javax.persistence.Converter;@Converter public class CoverConverter implements AttributeConverter<Cover, String> {@Overridepublic String convertToDatabaseColumn(Cover attribute) {switch (attribute) {case DUST_JACKET:return "D";case HARDCOVER:return "H";case PAPERBACK:return "P";default:throw new IllegalArgumentException("Unknown" + attribute);}}@Overridepublic Cover convertToEntityAttribute(String dbData) {switch (dbData) {case "D":return DUST_JACKET;case "H":return HARDCOVER;case "P":return PAPERBACK;default:throw new IllegalArgumentException("Unknown" + dbData);}} }

    好吧,親愛的讀者,我不會侮辱您,對此進行解釋。 將枚舉轉換為將存儲在關系數據庫中的任何內容,反之亦然。 從理論上講,如果使用以下聲明,JPA提供程序應自動應用轉換器:

    @Converter(autoApply = true

    它對我不起作用。 此外,在@Entity類中顯式聲明它們而不是@Enumerated也不起作用:

    import javax.persistence.Convert;//...@Convert(converter = CoverConverter.class) private Cover cover;

    導致異常:

    Exception Description: The converter class [com.blogspot.nurkiewicz.CoverConverter] specified on the mapping attribute [cover] from the class [com.blogspot.nurkiewicz.Book] was not found. Please ensure the converter class name is correct and exists with the persistence unit definition.

    錯誤或功能,我不得不在orm.xml提及轉換器:

    <?xml version="1.0"?> <entity-mappings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm" version="2.1"><converter class="com.blogspot.nurkiewicz.CoverConverter"/> </entity-mappings>

    它飛! 我可以自由修改我的Cover枚舉(添加,重新排列,重命名),而不會影響現有記錄。

    我想與您分享的一個技巧與可維護性有關。 每次您有一段從或到enum的代碼映射時,請確保已對其進行了正確的測試。 我并不是說要手動測試每個可能的現有值。 為了確保新的enum值在映射代碼中得到反映,我進行了更多測試。 提示:如果您添加新的enum值,但是忘記從中添加映射代碼,則下面的代碼將失敗(通過拋出IllegalArgumentException ):

    for (Cover cover : Cover.values()) {new CoverConverter().convertToDatabaseColumn(cover); }

    JPA 2.1中的自定義轉換器比我們所看到的有用得多。 如果將JPA與Scala結合使用,則可以使用@Converter將數據庫列直接映射到scala.math.BigDecimal , scala.Option或小寫類。 在Java中,最終將有一種可移植的方式來映射Joda時間 。 最后但并非最不重要的一點是,如果您喜歡(非常)強類型的域,則可能希望擁有PhoneNumber類(帶有isInternational() , getCountryCode()和自定義驗證邏輯),而不是String或long 。 JPA 2.1中的這一小增加肯定會顯著提高域對象的質量。

    如果您想使用此功能, 可以在GitHub上找到示例Spring Web應用程序。

    參考: Java和社區博客中的JCG合作伙伴 Tomasz Nurkiewicz 在JPA 2.1中使用@Convert進行了正確的映射枚舉 。

    翻譯自: https://www.javacodegeeks.com/2013/06/mapping-enums-done-right-with-convert-in-jpa-2-1.html

    總結

    以上是生活随笔為你收集整理的在JPA 2.1中使用@Convert正确完成映射枚举的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。