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

如果您曾经在JPA中使用过Java枚举,那么您肯定会意识到它们的局限性和陷阱。 使用enum作为@Entity的属性通常是一个很好的选择,但是2.1之前的JPA不能很好地处理它们。 它给了您2 + 1个选择:

托肖夫达林

托肖夫达林

  1. @Enumerated(EnumType.ORDINAL) (默认值)将使用Enum.ordinal()映射enum值。 基本上,第一个枚举值将在数据库列中映射为0 ,第二个映射为1 ,依此类推。这非常紧凑,并且在要修改枚举时非常有用。 在中间删除或增加值或重新排列它们将完全破坏现有记录。 哎哟! 更糟糕的是,单元测试和集成测试通常在干净的数据库上运行,因此它们不会发现旧数据之间的差异。
  2. @Enumerated(EnumType.STRING)更安全,因为它存储enum字符串表示形式。 现在,您可以安全地添加新值并移动它们。 但是,重命名Java代码中的enum仍会破坏DB中的现有记录。 更重要的是,这种表示非常冗长,不必要地消耗了数据库资源。
  3. 您还可以使用原始表示形式(例如single charint ),并在@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;//...
}

其中Coverenum

public enum Cover {PAPERBACK, HARDCOVER, DUST_JACKET}

ORDINALSTRING都不是一个很好的选择。 前者是因为以任何方式重新排列前三个值都会破坏现有记录的加载。 后者太冗长。 这是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.BigDecimalscala.Option或小写类。 在Java中,最终将有一种可移植的方式来映射Joda时间 。 最后但并非最不重要的一点是,如果您喜欢(非常)强类型的域,则可能希望拥有PhoneNumber类(带有isInternational()getCountryCode()和自定义验证逻辑),而不是Stringlong 。 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssh架构之hibernate(一)简单使用hibernate完成CRUD

1.Hibernate简介 Hibernate是一个开放源代码的对象关系映射(ORM)框架&#xff0c;它对JDBC进行了非常轻量级的对象封装&#xff0c;它将POJO与数据库表建立映射关系&#xff0c;是一个全自动的orm框架&#xff0c;hibernate可以自动生成SQL语句&#xff0c;自动执行&#xff0c…

使用AspectJ审计Spring MVC Webapp。 第1部分

如果您像我一样&#xff0c;那么您将拥有那种编程天&#xff0c;一切似乎都进展顺利。 您编写代码和测试&#xff0c;它就可以正常工作。 然后还有其他日子&#xff0c;非常糟糕的日子&#xff0c;在那儿&#xff0c;您知道所编写的所有内容都尽可能正确&#xff0c;并且代码拒…

GitHub注册和Git安装

一、注册GitHub GitHub官方地址&#xff1a;https://github.com。 在浏览器中打开GitHub网址&#xff0c;通过首页进行注册&#xff0c;如下图所示。 二、安装Git Git官方下载地址&#xff1a;http://git-scm.com/download/。 Git支持多平台&#xff08;Mac OS X/Windows/Linux…

如何存储和恢复 HTML5 Canvas 状态

当我们在 HTML5 Canvas 上使用其 2D 上下文进行图形绘制的时候&#xff0c;可以通过操作 2D 上下文的属性来绘制不同风格的图形&#xff0c;例如不同字体、填充等等。 通常情况下&#xff0c;在画布上的绘图时&#xff0c;您需要更改在绘制的2D背景下的状态。例如&#xff0c;你…

innodb和my查询速度_吃透MySQL:MyISAM和InnoDB存储引擎详细介绍

一&#xff0c;MySQL基本架构MySQL基础架构可以分为两大类&#xff1a;Server层和存储引擎层。Server层&#xff1a; Server层涵盖了MySQL大部分核心业务功能&#xff0c;并且所有存储引擎的功能都在这一层实现。存储引擎层&#xff1a;存储引擎有很多&#xff0c;各自有着各自…

Java EE EJB拦截器教程和示例

在此示例中&#xff0c;我们将看到如何在EJB中使用拦截器并使用简单的Web应用程序对其进行测试。 1.简介 顾名思义&#xff0c;当您想拦截对EJB方法的调用时&#xff0c;将使用拦截器。 如果为Bean声明一个拦截器&#xff0c;则每次调用该Bean的方法时&#xff0c;该拦截器的一…

Mac python Tesseract 验证码识别

Tesseract 简介 Tesseract(/tesərkt/) 这个词的意思是"超立方体"&#xff0c;指的是几何学里的四维标准方体&#xff0c;又称"正八胞体"。不过这里要讲的&#xff0c;是一款以其命名的开源 OCR(Optical Character Recognition, 光学字符识别) 软件。 所谓…

如何判断html页面停止滚动?

写在开始的话 查遍的文献&#xff0c;没有找到js或者jquery定义好的方法可用&#xff0c;最后迫不得已自己写了个方法。&#xff08;如果哪位同学知道有其他方法&#xff0c;欢迎讨论&#xff09; 代码 var count_index 0;$(window).scroll(function(e) {if(count_index 0) {…

php 打乱数组顺序_PHP实现大转盘抽奖算法

php中文网最新课程每日17点准时技术干货分享本文通过具体的实例向大家介绍了PHP语言实现大转盘抽奖算法&#xff0c;希望对大家学习PHP抽奖有所帮助。流程&#xff1a;1.拼装奖项数组&#xff1b;2.计算概率&#xff1b;3.返回中奖情况。代码如下&#xff1a;中奖概率 v 可以…

linux线程基础篇----线程同步与互斥

linux线程基础----线程同步与互斥 一、同步的概念 1.同步概念 所谓同步&#xff0c;即同时起步&#xff0c;协调一致。不同的对象&#xff0c;对“同步”的理解方式略有不同。如&#xff0c;设备同步&#xff0c;是指在两个设备 之间规定一个共同的时间参考&#xff1b;数据库同…

分布式系统开发注意事项

开发分布式软件系统时&#xff0c;要考虑许多因素。 如果您甚至不知道第一句话中我在说什么&#xff0c;那么让我为您提供一些见解&#xff0c;示例以及有关分布式系统的实例。 总览 分布式系统是指多个物理硬件设备与单独的离散用户交互并通过这些硬件设备协作以为这些离散的…

只需5步,轻松创建HTML5离线应用

1 – 添加 HTML5 doctype第一件要做的事情是创建一个符合规范的 HTML5 文档。HTML5 doctype 相比于 xhtml 版本的 doctype 而言&#xff0c;要简单明了得多&#xff1a; <!DOCTYPE html><html> ...创建一个名为 index.html 的文档&#xff0c;或者猛击这里下载这份…

Java EE 7发布–反馈和新闻报道

Java EE 7已经存在了几天。 我们所有人都有机会观看直播活动或可用的重播 。 最后的MR版本完成了将他们的工作推向JCP的过程&#xff0c;基本上是一个总结。 是时候反思发生的事情以及我对此的想法了。 启动活动中的社区参与 这不是一个大秘密。 即使Oracle的Java EE 7发行可以…

HTML5中的本地数据库-Web SQL Database

html5增加新的特性&#xff0c;那就是增加了本地存储&#xff01;改善用户体验&#xff0c;或许html5会带着我们走进新的互联网时代。 下面看看怎样操作web 数据库吧&#xff01;&#xff01;首先新建数据库&#xff01; var db window.openDatabase("mydata", &quo…

解决swiper-slide在ion-slide-box不滑动的问题(暂且这么描述)

1&#xff0c;开发环境ionic1angularjs1 嗯对的版本都是最低版本 页面结构想要完成的功能是这样的&#xff08;比较丑 &#xff0c;不接受批评&#xff0c;捂脸&#xff09; 大致如图 代码结构&#xff1a; <ion-slide-box><ion-slide> //列表 <div class"…

Win10 系统直接在目录下打开cmd

每次用cmd命令&#xff0c;就要定位到当前文件夹&#xff0c;很麻烦&#xff0c;于是想了下&#xff0c;可不可以直接定位到要操作的文件夹&#xff0c;百度了一下&#xff0c;果然&#xff0c;度娘没有让我失望&#xff0c; 美滋滋的试了下。真的可以。在此记录下&#xff0c;…

今日学到乱写

EXPLAIN 直接上图 一个个说&#xff1a; select_type 查询中每个select子句的类型&#xff08;简单OR复杂&#xff09; a. SIMPLE&#xff1a;查询中不包含子查询或者UNION b. 查询中若包含任何复杂的子部分&#xff0c;最外层查询则被标记为&#xff1a;PRIMARY c. 在SELECT或…

hash的算法 java_【数据结构与算法】一致性Hash算法及Java实践

追求极致才能突破极限一、案例背景1.1 系统简介首先看一下系统架构&#xff0c;方便解释&#xff1a;页面给用户展示的功能就是&#xff0c;可以查看任何一台机器的某些属性(以下简称系统信息)。消息流程是&#xff0c;页面发起请求查看指定机器的系统信息到后台&#xff0c;后…

Java EE CDI依赖关系消歧示例

在本教程中&#xff0c;我们将向您展示如何避免CDI bean中的依赖关系消除歧义。 在CDI中&#xff0c;我们可以为应用程序中不同客户端的接口的多个实现实现依赖项注入。 依赖关系消除歧义的问题是客户端如何在不同的实现中调用特定的实现&#xff0c;而不会发生任何错误。 为了…

linux java 安装配置_类Linux环境安装jdk1.8及环境变量配置详解

配置很简单&#xff0c;但是每次都要查一下&#xff0c;索性就记录下1. 安装前准备1.1 创建安装目录&#xff0c;习惯上通常安装在/usr/local/jdk8目录下mkdir /usr/local/jdk81.2 查看是否安装过jdk&#xff0c;安装前要把之前的删除干净# 通过jdk环境变量查看echo $JAVA_HOME…