在spring data jpa中使用自定义转换器之使用枚举转换

转载请注明http://www.cnblogs.com/majianming/p/8553217.html

在项目中,经常会出现这样的情况,一个实体的字段名是枚举类型的

我们在把它存放到数据库中是需要将其映射为字符串或者其他类型

 1  public enum Color{
 2     
 3         RED(1, "RED"),
 4         ORANGE(2, "ORANGE");
 5 
 6         private Integer rainbowIndex;//在彩虹中的序号
 7         private String name;
 8 
 9         Type(Integer rainbowIndex, String name) {
10             this.rainbowIndex= rainbowIndex;
11             this.name= name;
12         }
13 
14         public Integer getRainbowIndex() {
15             return rainbowIndex;
16         }
17 
18         public String getName() {
19             return name;
20         }
21
22 public static Type getTypeFromName(String name){ 23 for (Type type : Type.values()) { 24 if (type.getName().equals(name)){ 25 return type; 26 } 27 } 28 return null; 29 } 30 }

 

@Entity
@Table(name = "tb_paper")
public class Paper {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long no;

    private Color color;

    public Long getNo() {
        return no;
    }

    public void setNo(Long no) {
        this.no= no;
    }
    public Color getColor() {
        return type;
    }

    public void setColor(Color type) {
        this.type = type;
    }


}

如果这样直接写,会怎样?

在保存到数据库时没有错误信息,它帮我们生成一张表,而且还把其中一个字段rainbowIndex映射到了数据表tb_paper上的color字段(从参数类型上可以看出),

CREATE TABLE `tb_paper` (
  `no` bigint(20) NOT NULL AUTO_INCREMENT,
  `color` int(11) DEFAULT NULL,
  PRIMARY KEY (`no`)
) DEFAULT CHARSET=utf8;

 

那我两个参数在实体中都是String类型的,框架会帮我如何选择?

 1  public enum Color{
 2     
 3         RED("1", "RED"),
 4         ORANGE("2", "ORANGE");
 5 
 6         private String rainbowIndex;//在彩虹中的序号 我们这里改成String类型 虽然使用数值类型比较恰当
 7         private String name;
 8 
 9         Type(String rainbowIndex, String name) {
10             this.rainbowIndex= rainbowIndex;
11             this.name= name;
12         }
13 
14         public String getRainbowIndex() {
15             return rainbowIndex;
16         }
17 
18         public String getName() {
19             return name;
20         }
21
22 public static Type getTypeFromName(String name){ 23 for (Type type : Type.values()) { 24 if (type.getName().equals(name)){ 25 return type; 26 } 27 } 28 return null; 29 } 30 }

发现数据库还是 `color` int(11) DEFAULT NULL ,这就肯定不对了

那么这里出现了两个问题

  1. 映射的类型错误
  2. 映射的字段不能指定

我们使用jpa2.1规范里面的属性转换器

 1 @Converter(autoApply = true)
 2 public class ColorConverter implements AttributeConverter<Color, String> {//泛型指的是你在实体用的类型,第二个是指需要映射到数据库的类型对应的java中的类型
 3 
 4     @Override
 5     public String convertToDatabaseColumn(Color attribute) {
 6         return attribute.getName();
 7     }
 8 
 9     @Override
10     public Color convertToEntityAttribute(String dbData) {
11         return Color.getColorFromName(dbData);
12     }
13 }

看下数据库表 `color` varchar(255) DEFAULT NULL ,字段映射对了,需要注意的是如果上面注解@Converter的没有(autoApply = true),(默认)表示在所有用到Color类型的实体映射是将默认映射为Integer类型,其实就是不生效,如果需要全局生效,加上(autoApply = true)就可以了,如果需要对于一个实体的一个属性单独处理的话,在需要的属性加上@Convert(converter = ColorConverter.class)


参考

  http://hantsy.blogspot.com/2013/12/jpa-21-attribute-converter.html

  https://www.thoughts-on-java.org/jpa-21-how-to-implement-type-converter/

 


转载请注明http://www.cnblogs.com/majianming/p/8553217.html

posted @ 2018-03-13 01:51  铭mc  阅读(2223)  评论(0编辑  收藏  举报