[英]Store ENUM value into database
我想使用 ENUM 将值映射到数据库表行中:
业务客户搜索参数:
@Getter
@Setter
public class BusinessCustomersSearchParams {
private String title;
private List<String> status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
规格:
@Override
public Page<BusinessCustomersFullDTO> findBusinessCustomers(BusinessCustomersSearchParams params, Pageable pageable)
{
Specification<BusinessCustomers> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (params.getTitle() != null) {
predicates.add(cb.like(cb.lower(root.get("description")), "%" + params.getTitle().toLowerCase() + "%"));
}
final List<String> statuses = Optional.ofNullable(params.getStatus()).orElse(Collections.emptyList());
if (statuses != null && !statuses.isEmpty()){
List<BusinessCustomersStatus> statusesAsEnum = statuses.stream()
.map(status -> BusinessCustomersStatus.fromStatus(status))
.collect(Collectors.toList())
;
predicates.add(root.get("status").in(statusesAsEnum));
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
};
return businessCustomersService.findAll(spec, pageable).map(businessCustomersMapper::toFullDTO);
}
属性转换器:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter
public class BusinessCustomersStatusAttributeConverter
implements AttributeConverter<BusinessCustomersStatus, String> {
public String convertToDatabaseColumn( BusinessCustomersStatus value ) {
if ( value == null ) {
return null;
}
return value.getStatus();
}
public BusinessCustomersStatus convertToEntityAttribute( String value ) {
if ( value == null ) {
return null;
}
return BusinessCustomersStatus.fromStatus( value );
}
}
枚举:
package org.merchant.database.service.businesscustomers;
public enum BusinessCustomersStatus {
A("active"),
O("onboarding"),
N("not_verified"),
V("verified"),
S("suspended"),
I("inactive");
private String status;
BusinessCustomersStatus(String status)
{
this.status = status;
}
public String getStatus() {
return status;
}
public static BusinessCustomersStatus fromStatus(String status) {
switch (status) {
case "active": {
return A;
}
case "onboarding": {
return O;
}
case "not_verified": {
return NV;
}
case "verified": {
return V;
}
case "suspended": {
return S;
}
case "inactive": {
return I;
}
default: {
throw new UnsupportedOperationException(
String.format("Unkhown status: '%s'", status)
);
}
}
}
}
实体:
@Entity
@Table(name = "business_customers")
public class BusinessCustomers implements Serializable {
..........
@Convert( converter = BusinessCustomersStatusAttributeConverter.class )
private BusinessCustomersStatus status;
......
}
完整代码示例: https : //github.com/rcbandit111/Search_specification_POC
我发送带有 params list?size=5&page=0&status=active,suspended
http 查询,结果得到大写字母“status”:“ACTIVE”。
我想使用status=active
从 FE 搜索并获取状态的状态,但仅将符号 A 存储到数据库行字段中。
如何将 ENUM 键 A 存储到数据库中?
为了在数据库中存储实际的枚举值,您可以做两件事。
一,按照@PetarBivolarski 的建议,修改AttributeConverter
convertToDatabaseColumn
方法并返回value.name()
而不是value.getStatus()
。 但请注意,此外,您还需要更新convertToEntityAttribute
以考虑该更改:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter
public class BusinessCustomersStatusAttributeConverter
implements AttributeConverter<BusinessCustomersStatus, String> {
public String convertToDatabaseColumn( BusinessCustomersStatus value ) {
if ( value == null ) {
return null;
}
return value.name();
}
public BusinessCustomersStatus convertToEntityAttribute( String value ) {
if ( value == null ) {
return null;
}
return BusinessCustomersStatus.valueOf( value );
}
}
如果您考虑一下,更直接的解决方案是将status
字段保留为@Enumerated
:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Entity
@Table(name = "business_customers")
public class BusinessCustomers {
//...
@Enumerated(EnumType.STRING)
@Column(name = "status", length = 20)
private BusinessCustomersStatus status;
//...
}
此外,它更多地取决于您的代码的其余部分。
关于您的第二个问题,应用程序返回"status":"ACTIVE"
因为在BusinessCustomersFullDTO
您将状态字段定义为String
并且该字段接收由@Mapstruct
和BusinessCustomersMapper
执行的映射过程的结果。
为了解决这个问题,正如我之前建议你的,你可以修改你的Mapper
来处理所需的自定义转换:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.merchant.config.BaseMapperConfig;
import org.merchant.database.entity.BusinessCustomers;
import org.merchant.database.service.businesscustomers.BusinessCustomersStatus;
import org.merchant.dto.businesscustomers.BusinessCustomersFullDTO;
@Mapper(config = BaseMapperConfig.class)
public interface BusinessCustomersMapper {
@Mapping(source = "status", target = "status", qualifiedByName = "businessCustomersToDTOStatus")
BusinessCustomersFullDTO toFullDTO(BusinessCustomers businessCustomers);
@Named("busineessCustomersToDTOStatus")
public static String businessCustomersToDTOStatus(final BusinessCustomersStatus status) {
if (status == null) {
return null;
}
return status.getStatus();
}
}
如果您不喜欢这种解决方案,也许您可以采取不同的方法:它将包括以下内容。 这个想法是修改BusinessCustomersFullDTO
的 Jackson 序列化和反序列化行为。 实际上,在您的用例中只需要修改序列化逻辑。
首先,定义status
在现场BusinessCustomersFullDTO
来讲BusinessCustomersStatus
还有:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class BusinessCustomersFullDTO {
private long id;
private String name;
private String businessType;
private BusinessCustomersStatus status;
private String description;
private String country;
private String address1;
}
要完成该解决方案,请在BusinessCustomersStatus
枚举中执行以下更改:
public enum BusinessCustomersStatus {
A("active"),
O("onboarding"),
NV("not_verified"),
V("verified"),
S("suspended"),
I("inactive");
private String status;
BusinessCustomersStatus(String status)
{
this.status = status;
}
// Define the status field as the enum representation by using @JsonValue
@JsonValue
public String getStatus() {
return status;
}
// Use the fromStatus method as @JsonCreator
@JsonCreator
public static BusinessCustomersStatus fromStatus(String status) {
if (StringUtils.isEmpty(status)) {
return null;
}
switch (status) {
case "active": {
return A;
}
case "onboarding": {
return O;
}
case "not_verified": {
return NV;
}
case "verified": {
return V;
}
case "suspended": {
return S;
}
case "inactive": {
return I;
}
default: {
throw new UnsupportedOperationException(
String.format("Unkhown status: '%s'", status)
);
}
}
}
}
请注意包含@JsonValue
和@JsonCreator
注释:后者用于反序列化,这在您的应用程序中对我来说似乎是不必要的,但以防万一。
请参阅提供的 Jackson 注释的相关文档。
注意BusinessCustomersStatusAttributeConverter
convertToDatabaseColumn()
方法。
它应该返回value.name()
而不是value.getStatus()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.