公司内部网站规划,网站建设哈尔滨,微信小程序开发实战课后答案,希爱力双效片副作用如果您曾经在JPA中使用过Java枚举#xff0c;那么您肯定会意识到它们的局限性和陷阱。 使用enum作为Entity的属性通常是一个很好的选择#xff0c;但是2.1之前的JPA不能很好地处理它们。 它给了您2 1个选择#xff1a; 托肖夫达林 Enumerated(EnumType.ORDINAL) #xf… 如果您曾经在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实现因此我们将使用它进行一些实验。 我们将从作为“ 穷人的CRUDjqGridRESTAJAX和Spring MVC一屋子 ”的一部分开发的示例Spring应用程序开始。 该版本没有持久性因此我们将在由Eclipselink支持的Spring Data JPA之上添加薄DAO层。 到目前为止只有实体是Book Entity
public class Book {IdGeneratedValue(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 AttributeConverterCover, 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 version1.0?
entity-mappings xmlnshttp://www.eclipse.org/eclipselink/xsds/persistence/orm version2.1converter classcom.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