【Spring Data Jpa 03】Spring Data Jpa对枚举类型的处理

在日常的开发中,我们常常经常会使用到枚举类型。如前端用户性别显示为男女,而数据库中存储的是0或者1。本文在数据持久层是JPA的情况下,记录如何使用枚举类型。

本文主要有以下内容:

  • Spring Data Jpa对枚举类型的处理

前置条件:具体过程省略,创建spring boot工程,并引入相关依赖。

依赖文件如下:

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.7.14</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>2.7.14</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

配置文件配置:

yml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/datajpa?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
  jpa:
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL8Dialect
    database: mysql
    generate-ddl: true
    open-in-view: true
# 这里的配置是为了解决如果我们的实体类中有MySQL关键字相同的属性,添加此配置可以建表成功。但是一般是不要使用相关的关键字属性。
#    properties:
#      hibernate:
#        globally_quoted_identifiers: true
server:
  port: 8585

实体类创建

创建一个实体类,代码如下

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "table_meta")
@EntityListeners(AuditingEntityListener.class)
public class MetaEntity {
​
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "meta_id")
    private Long metaId;
​
    @Column(name = "type_id")
    private Long typeId;
​
    @Column(name = "key_name")
    private Long keyName;
​
    @Column(name = "meta_status",nullable = false)
    private MetaStatusEnum metaStatus;
​
    @CreatedDate
    @Column(name = "created_time",nullable = false)
    private Date createdTime;
​
}
  • @Entity@Table:用于标识这是一个实体类且与之关联的数据表名。
  • @EntityListeners(AuditingEntityListener.class):用于自动填充createdTime属性
  • @CreatedDate:表示此纪录的创建时间,和本文所讨论的内容无关,可忽略,该注解需要在类上添加@EntityListerers注解配合使用

创建枚举类

在实体类中使用的枚举类如下:

java 复制代码
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum MetaStatusEnum {
    AVAILABLE("未使用", 1),
    USED("已用", 2),
    INACTIVE("已经注销", 3);
​
    private String desc;
    private Integer code;
​
    public static MetaStatusEnum convert(Integer code) {
        if (code == null) {
            return null;
        }
        return Stream.of(values())
                .filter(bean -> bean.code.equals(code))
                .findAny()
                .orElse(null);
    }
}

在此类中定义了一个convert方法用于通过code得到对应的枚举对象,

创建枚举类转换器

jpa中,提供了一个AttributeConverter接口,用于处理枚举类到DB或者DB到JavaBean。因此我们只需要实现这个接口即可!

java 复制代码
@Converter(autoApply = true)
public class MetaStatusEnumConvert implements
        AttributeConverter<MetaStatusEnum, Integer> {
​
    // enum to DB value
    @Override
    public Integer convertToDatabaseColumn(MetaStatusEnum metaStatusEnum) {
        return metaStatusEnum.getCode();
    }
​
    // db to javaBean
    @Override
    public MetaStatusEnum convertToEntityAttribute(Integer code) {
        return MetaStatusEnum.convert(code);
    }
}
  • convertToDatabaseColumn():将我们的枚举对象转换为数据库中存储的值。
  • convertToEntityAttribute():将数据库中存储的值转换为枚举对象
  • 使用@Converter(autoApply = true)标注此类

在写完转换器之后,在实体类上的枚举属性上添加@Convert(converter = MetaStatusEnumConvert.class)指定枚举转换器,这样就可以正常工作了。

java 复制代码
@Column(name = "meta_status",nullable = false)
@Convert(converter = MetaStatusEnumConvert.class)
private MetaStatusEnum metaStatus;

完成上述工作后,简单定义一下daoservice接口代码。

java 复制代码
@Repository
public interface MetaRepository extends JpaRepository<MetaEntity,Long> {
    MetaEntity findMetaEntityByMetaId(Long id);
}
public interface MetaServiceInt {
    MetaEntity findMetaEntityByMetaId(Long id);
    MetaEntity insertMeta(MetaEntity entity);
}
// service实现代码
@Service
public class MetaServiceImpl implements MetaServiceInt {
    @Resource
    MetaRepository metaRepository;
    @Override
    public MetaEntity findMetaEntityByMetaId(Long id) {
        return metaRepository.findMetaEntityByMetaId(id);
    }
    @Override
    public MetaEntity insertMeta(MetaEntity entity) {
        return metaRepository.save(entity);
    }
}

接下来是controller层代码

java 复制代码
@RestController
@CrossOrigin(allowedHeaders = "*", origins = "*")
@RequestMapping("meta/")
public class MetaController {
​
    @Resource
    MetaServiceInt metaService;
​
    @GetMapping("find.do")
    public MetaEntity findMetaByMetaId(Long metaId) {
        return metaService.findMetaEntityByMetaId(metaId);
    }
​
    @PostMapping("insert.do")
    public MetaEntity insertMeta(MetaEntity entity) {
        return metaService.insertMeta(entity);
    }
​
}

启动类配置:

java 复制代码
@SpringBootApplication
@EntityScan("com.jpa.tutorial.entity")
@EnableJpaAuditing
public class JpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(JpaApplication.class);
    }
}
  • @EnableJpaAuditing:是为了能够让@CreatedDate正常工作。

Postman测试结果如下图:

数据库结果如下:

可以看到接口达到预期效果:

  • createdTime:自动填充
  • 枚举类型正常工作

Spring Data Jpa相关文章:

相关推荐
CaffeinePro43 分钟前
Pydantic深度使用:数据校验、枚举、ORM映射
后端·fastapi
Chenyiax1 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH1 小时前
Koa和Express的区别
后端
MariaH1 小时前
Koa框架的使用
后端
luckdewei2 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某4 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy4 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom4 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
唐青枫8 小时前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
用户1474853079748 小时前
CodeX使用Skill生成游戏美术和音乐资源,一分钟入门
后端