在JPA注解中,有个@Convert注解,其中需要传入一个Class作为convert参数,该class需要实现AttributeConverter<X,Y>接口。下面来看看AttributeConverter接口的作用。
AttributeConverter<X,Y>
实体属性类型转换器。主要使用场景:
持久化enum
加解密数据
持久化日期
简单化操作,用持久化enum枚举来进行一个操作。AttributeConverter<X,Y>该接口中需要实现两个方法:
y convertToDatabaseColumn(x) 作用:将实体属性x转化为y存储到数据库中,即插入和更新操作时执行;
x convertToEntityAttribute(y) 作用:将数据库中的字段y转化为实体属性x,即查询操作时执行。
场景:用户登录时,记录用户的动作:登录,登出,注册,重置密码。
创建一个枚举类UserAction
* 用户操作枚举.
* @author Wang.ch
public
enum
UserAction
{
REG
(
0
,
"注册"
)
,
RESET
(
1
,
"重置密码"
)
,
LOGIN
(
2
,
"用户登录"
)
,
LOGOUT
(
3
,
"用户登出"
)
;
private
int
value
;
private
String
desc
;
UserAction
(
int
value
,
String
desc
)
{
this
.
value
=
value
;
this
.
desc
=
desc
;
public
int
getValue
(
)
{
return
value
;
public
void
setValue
(
int
value
)
{
this
.
value
=
value
;
public
String
getDesc
(
)
{
return
desc
;
public
void
setDesc
(
String
desc
)
{
this
.
desc
=
desc
;
public
static
class
Convert
implements
AttributeConverter
<
UserAction
,
Integer
>
{
@Override
public
Integer
convertToDatabaseColumn
(
UserAction
attribute
)
{
return
attribute
==
null
?
null
:
attribute
.
getValue
(
)
;
@Override
public
UserAction
convertToEntityAttribute
(
Integer
dbData
)
{
for
(
UserAction
type
:
UserAction
.
values
(
)
)
{
if
(
dbData
.
equals
(
type
.
getValue
(
)
)
)
{
return
type
;
throw
new
RuntimeException
(
"Unknown database value: "
+
dbData
)
;
其中,在已经把转换类Convert写入到了枚举当中。
在实体内中添加注解
@Convert(converter = UserAction.Convert.class)
private UserAction action;
从转换类中的方法可以看出,在写入数据库时,jpa会调用convert的convertToDatabaseColumn方法,把UserAction枚举的value写入到库中,在反向查询时,通过数据库的值和遍历的枚举的value进行比较,然后返回UserAction实体。
数据的加密和日期的转换也就类似的操作了。
但是这样的每个枚举可能都要去写这样的转换类,可能会存在重复的操作。可以尝试写个通用的枚举转换类。
所有的枚举都实现一个接口:BaseEnum.java
写一个抽象类去实现AttributeConverter<X,Y>:BaseEnumConverter<X,Y>
所有的枚举中定义一个public静态类继承抽象类
BaseEnum.java
* 枚举基类.
* @author Wang.ch
* @param <T> 数据库存储的java类型
public interface BaseEnum<Y> {
* 存取到数据库中的值.
* @return
public Y getValue();
BaseEnumConverter.java
public abstract class BaseEnumConverter<X extends BaseEnum<Y>, Y> implements AttributeConverter<BaseEnum<Y>, Y> {
private Class<X> xclazz;
private Method valuesMethod;
@SuppressWarnings("unchecked")
public BaseEnumConverter() {
this.xclazz = (Class<X>) (((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments())[0];
try {
valuesMethod = xclazz.getMethod("values");
} catch (Exception e) {
throw new RuntimeException("can't get values method from " + xclazz);
@Override
public Y convertToDatabaseColumn(BaseEnum<Y> attribute) {
return attribute == null ? null : attribute.getValue();
@SuppressWarnings("unchecked")
@Override
public X convertToEntityAttribute(Y dbData) {
try {
X[] values = (X[]) valuesMethod.invoke(null);
for (X x : values) {
if (x.getValue().equals(dbData)) {
return x;
} catch (Exception e) {
throw new RuntimeException("can't convertToEntityAttribute" + e.getMessage());
throw new RuntimeException("unknown dbData " + dbData);
修改后的枚举:UserAction.java
* 用户操作枚举.
* @author Wang.ch
public enum UserAction implements BaseEnum<Integer> {
REG(0, "注册"), RESET(1, "重置密码"), LOGIN(2, "用户登录"), LOGOUT(3, "用户登出");
private Integer value;
private String desc;
UserAction(Integer value, String desc) {
this.value = value;
this.desc = desc;
public Integer getValue() {
return value;
public void setValue(Integer value) {
this.value = value;
public String getDesc() {
return desc;
public void setDesc(String desc) {
this.desc = desc;
public static class Convert2 extends BaseEnumConverter<UserAction, Integer>{
需要注意的是,在上面的代码中,BaseEnumConverter使用了BaseEnum作为X的限定类型,但是实际上并未能真正限定传入的数据类型是一个枚举类型,显然BaseEnumConverter只适用于枚举类型,因为在类初始化时,使用了values这个Method反射,只有枚举类型才有。在其他的值类型转换时,可以参照枚举自定义其他的X限定类型。
小技巧,如果枚举没有这么复杂,则完全可以用@Enumerated(EnumType.ORDINAL)和@Enumerated(EnumType.STRING)让数据库自动进行转换。
参考链接:https://www.jianshu.com/p/15f5b7062eac
可以使用JPA 2.0保留枚举,但是没有很好的方法来实现。 使用@Enumerated批注,可以使用EnumType.ORDINAL或EnumType.STRING将枚举值映射到其数据库表示形式。 但是这两种选择都有一些缺点,我们将在本文的第一部分中进行讨论。 在第二部分中,我将向您展示通过使用JPA 2.1类型转换器来避免这些缺点。
使用JPA 2.0持久枚举
EnumType.ORD...
目录前言具体实现Map与JSON的
属性转换
器List与JSON
属性转换
器实体应用效果图
@Convert
属性转换
器用于数据库
属性类型与
java存储的类型做转换,其方便之处在于存储与读取的时候能自动转换,如下业务场景:
业务对象存在一个Map或List
属性,存入数据库时需保存为json字符串,返回前端时以对象来返回。
@Convert
属性转换
器需实现
AttributeConverter<X, Y>接口,第一个泛型类型为Entity字段类型,第二个泛型类型为数据库字段类型。
JPA踩坑记:Spring Data Jpa 原生SQL联表查询返回自定义DTO
关键字: JPA复杂查询,JPA返回自定义实体,JPA返回自定义DTO,JPA联表查询,JPA原生SQL查询,JPA踩坑
新冠疫情之下,闲来无事研究了一下JPA,发现坑还是不少的,特地记录一下,有兴趣的道友可以看看。
在灵活性上JPA比不上MyBatis,比如想联表查询返回一个自定义的实体Dto,结果发现不能直...
3.8 类型转换原理与设置
Spring为我们提供了ConversionService接口用来做类型转换,它是Spring类型转换系统的入口。像我们注册的Formatter的FormattingConversionService类就是它的实现类。
FormattingConversionService支持注册Formatter、Converter和AnnotationFormatterFactory,它属于配置初始化数据绑定的一部分。
3.8.1 Formatter
Formatter用于格式化(id|na
开发过程中我们可能会遇到这样的问题。如何将一个Map<String,String>(一个Object)保存到数据库中,很多人的第一想法是这个简单。只要我们持久化的时候将这个Map转换成一个JSON以String的形式保存即可。
今天我们换一个新的方式去实现这个功能:
首先我们要了解一个东西AttributeConverters属性转换器
第一步:实现一个AttributeConve...
public class Boolean
Converter implements
AttributeConverter<Boolean, Integer> {
2.
属性注解
@Column(name = "VALID")@Convert(
converter = Boolean
Converter.class)
转载于:https://www.cnblogs.c...
AttributeConverter
javax.persistence.AttributeConverter
开发中有一个问题,有一个业务对象,它的属性是一个JSONObject对象,但是我们希望存入数据库时,存为json字符串。前端在插入和查询时,都是以对象来处理,所以希望能自动转换,即在插入数据库时,转为字符串,查询出来后转为对象。这就用到了今天要说的属性转换器。
第一步:定义一个属性转换器...
在真实的生产环境中,我们可能会把某些对象转换成json数据存到数据库,等到需要的时候再把这些数据取出来。
1、我们可以在数据库中添加一个class字段,存放该类的全路径,取出来的时候把json数据和class字段取出来,然后可以使用 fastjson等三方工具转成对象。
2、上面这种方式是通用的,不过在jpa中可以简化这个操作 。使用到的对象就是AttributeConve...
最近将项目由mybatis 修改为 jpa,遇到一个问题.
描述: 实体中的成员属性的类型是数组,在mybatis的xml中对该数组类型的属性进行了处理,而在jpa中,认为数组是(一对一或者一对多或者多对多)的关系映射
提示如下错误: 意思是无法进行序列化,在网上查找n多资料都说要加 关系注解,ranbinluan
org.springframework.orm.jpa.JpaSystemExc...
用于数据库属性类型与java存储的类型做转换,例如枚举类型,在存储到数据库时或者在数据库取出来时,不用手动转换。
必须实现接口AttributeConverter<X,Y>,源码如下:
package javax.persistence;
* A class that implements this interface can be used to conver...