问题描述
我正在尝试使用一个枚举来显示“权限”字段(读取,写入等)的人类可读值。当我将记录存储在关联的MysqL表中时,权限枚举字段需要转换为关联的整数(1、2、4等)。但是,当我运行SpringBoot应用程序并调用POST端点时,却遇到了一个奇怪的sql异常。例外:
无法执行DbAction.InsertRoot(entity = Invite(id = null,createdAt = 2020-09-19 18:12:01,createdBy = 1,listId = 8,token = c3b95dc9-ec4d-4dde- a461-b12746afa61e,expiresAt = 2020-09-26 18:12:01,权限= 2),generatedId = null)],其根本原因是 java.sql.sqlException:错误的整数值:第1行的“ permission”列的“ WRITE” 在com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:129)〜[mysql-connector-java-8.0.19.jar:8.0.19]
令我感到奇怪的是,db操作将报告要插入的“ permission”字段为2,但是sql异常报告“ WRITE”不是有效的整数值。知道我可能会缺少什么吗?
这是值得注意的代码和配置。请注意,我使用的是JDBC,而不是JPA:
这是枚举类:
public enum Permission {
READ(1),WRITE(2),CREATE(4),DELETE(8),ADMIN(16);
private Integer value;
Permission(final Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
//@JsonCreator
@Override
public String toString() {
return this.getValue().toString();
}
//@JsonValue
public static Permission forValue(final String name) {
return Permission.valueOf(name);
}
}
以下是POJO /实体:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
@Data
@AllArgsConstructor
@Builder
@ToString
public class Invite {
public static final int TOKEN_MINIMUM_LENGTH = 36;
public static final int TOKEN_MAXIMUM_LENGTH = 40;
@Id
private Long id;
private String createdAt;
private String createdBy;
private Long listId;
private String token;
private String expiresAt;
private Permission permission;
}
这是JdbcCustomConversions。应该注意的是,在调试时,ReadingConverter似乎已跳闸,但WritingConverter却没有。我不确定这是否是问题的一部分。
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import java.util.Arrays;
@Configuration
@EnableAutoConfiguration
public class JdbcConfiguration extends AbstractJdbcConfiguration {
/**
* JDBC Custom Conversions.
*
*/
@Override
public JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(Arrays.asList(PermissionToInteger.INSTANCE,IntegerToPermission.INSTANCE));
}
// I have never seen this get tripped
@WritingConverter
enum PermissionToInteger implements Converter<Permission,Integer> {
INSTANCE;
@Override
public Integer convert(final Permission permission) {
return permission == null ? null : permission.getValue();
}
}
// this one trips in the debugger and appears to be working fine
@ReadingConverter
enum IntegerToPermission implements Converter<Integer,Permission> {
INSTANCE;
@Override
public Permission convert(final Integer code) {
for (final Permission perm: Permission.values()) {
if (perm.getValue().equals(code)) {
return perm;
}
}
return null;
}
}
}
这是简单的存储库:
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
import java.util.Optional;
public interface InviteRepository extends CrudRepository<Invite,Long> {
@Query("SELECT * from invite where token = :token")
Optional<Invite> findByToken(String token);
@Query("SELECT * from invite where created_by = :userId")
List<Invite> findByUserId(Long userId);
@Query("SELECT * from invite where list_id = :wishlistId")
List<Invite> findByWishlistId(Long wishlistId);
}
任何提示将不胜感激!
亚伦
解决方法
解决方法是将WritingConverter更改为String而不是Integer:
@WritingConverter
public enum PermissionToInteger implements Converter<Permission,String> {
INSTANCE;
@Override
public String convert(final Permission permission) {
return permission == null ? null : permission.getValue().toString();
}
}
,
spring jdbc 的一些调试源码后,可以通过目标类从 JdbcValue 类赋值,将 enum 类型转换为整数。
@Bean
override fun jdbcCustomConversions() = JdbcCustomConversions(arrayListOf(
@WritingConverter
object: Converter<LoginTypes,JdbcValue> {
override fun convert(p0: LoginTypes) = JdbcValue.of(p0.code,JDBCType.INTEGER)
},@ReadingConverter
object:Converter<Int,LoginTypes>{
override fun convert(p0: Int): LoginTypes? = LoginTypes.values().first { it.code==p0 }
}```