java - 尽管 autoApply=false 且属性未使用 @Convert 注释,但仍应用 JPA 属性转换器
问题描述
我正在研究的系统有一堆旧数据,其中布尔值存储为'Y'
和'N'
。新表使用BIT
列代替,并简单地存储0
和1
。没有表格混合了这两种方法。
为了支持遗留表,我们有以下转换器:
@Converter(autoApply = false)
public class BooleanToStringConverter implements AttributeConverter<Boolean, String> {
private Logger.ALogger Log = Logger.of(BooleanToStringConverter.class);
@Override
public String convertToDatabaseColumn(final Boolean attribute) {
Log.debug("Converting the boolean value {}", attribute);
if (attribute == null) {
return "N";
}
return attribute ? "Y" : "N";
}
@Override
public Boolean convertToEntityAttribute(final String dbData) {
return "Y".equalsIgnoreCase(dbData);
}
}
由于这只需要应用于某些实体,因此 autoApply 属性已设置为 false。
我现在正在创建一个带有新表的全新实体。它有两个布尔属性,都使用 BIT 列样式而不是 Y/N:
@Entity
@Table(name = "MyEntity")
public class MyEntity {
@Id
@Column(name = "MyEntityId")
private Long id;
@Column(name = "IsClosed")
private Boolean closed;
...
}
请注意,我没有应用@Convert
注释。
我有一个查询需要过滤掉实体关闭的任何行:
query.where().eq(CLOSED, Boolean.FALSE)
正是在这一点上,我的问题出现了。每当运行此查询时,我都会看到来自 BooleanToStringConverter 的日志消息被写入日志,实际上,如果我转储从 MySQL 数据库执行的实际 SQL,那么我可以看到转换器确实应用于布尔属性,创建以下 SQL 片段:
select <columns>
from MyEntity t0
where <other predicates>
and t0.IsClosed = 'N'
order by <order clause>
这显然是错误的 - 不应该应用转换器,它没有设置为自动,并且关闭的属性没有用@Convert
.
我试图通过创建第二个转换器来解决这个问题:
@Converter(autoApply = true)
public class BooleanConverter implements AttributeConverter<Boolean, Boolean> {
private Logger.ALogger Log = Logger.of(BooleanConverter.class);
@Override
public Boolean convertToDatabaseColumn(final Boolean attribute) {
Log.debug("Processing the value {}.", attribute);
return attribute;
}
@Override
public Boolean convertToEntityAttribute(final Boolean dbData) {
return dbData;
}
}
这导致两个转换器都应用于该属性,并且我看到两个调试语句都出现在日志中。
2019-07-29 14:19:53,994 [dispatcher-69] DEBUG BooleanConverter Processing the value false.
2019-07-29 14:19:53,994 [dispatcher-69] DEBUG BooleanToStringConve I'm Converting the boolean value false
接下来,我尝试显式设置转换器以在实体本身上使用(我希望这可能会改变应用转换器的顺序,以便尽管其他转换器正在运行,但最终结果为真/假):
@Entity
@Table(name = "MyEntity")
public class MyEntity {
@Id
@Column(name = "MyEntityId")
private Long id;
@Convert(converter = BooleanConverter.class)
@Column(name = "IsClosed")
private Boolean closed;
...
}
结果完全相同;两个转换器都按顺序应用于值,BooleanToStringConverter
笑到最后并破坏谓词。
我宁愿保留它,BooleanToStringConverter
因为它可以减少处理遗留数据的痛苦,但除非我能弄清楚为什么在不应该应用它的时候应用它,否则我可能不得不删除它。
我正在使用 Ebean 版本 4.1.3 和 Play!2.6.21
我怎样才能阻止这个流氓转换器将自己应用于它无权触摸的属性?
解决方案
这是 Ebean 的一个(现在)已知限制,如Ebean 的 GitHub 页面上的Issue 1777所述。在撰写本文时,不打算修复它。
推荐阅读
- c++ - 如何在不知道其名称的情况下检查某个进程是否正在运行
- sql - 如何根据用户的选择处理 groupby 行中的字段顺序?
- javascript - 使用一个提交按钮/onsubmit 调用两个函数
- android - 最电池友好的周期性任务方法
- c# - 如何在不重定向标准输出的情况下读取进程的控制台输出?
- spring-batch - 可以在运行时向 ClassifierCompositeItemWriter 添加更多 ItemWriter
- html - ngb-progressbar 没有出现
- xslt - 带有模板标签新名称的 xsl 循环
- python - 为什么它会跳过我的 python 3.x 代码中的“if”语句以获取简单的 RockPaperScissors?
- ecmascript-6 - 在模块级别或函数级别定义 const 的性能差异