java-自定义验证注释引入了ConcurrentModificationException
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java-自定义验证注释引入了ConcurrentModificationException,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4747字,纯文字阅读大概需要7分钟。
内容图文
![java-自定义验证注释引入了ConcurrentModificationException](/upload/InfoBanner/zyjiaocheng/680/3b9cb3e393b54e7dbd49385462a6da42.jpg)
我的任务是为自定义验证创建注释.这是由于handling database constraint violations nicely.的一些问题,我对此所做的响应相对简单.我专门为需要它的一个域类创建了一个类级的CustomConstraint.我得到的当前结果如下:
@UniqueLocation注释:
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueLocationValidator.class)
@Documented
public @interface UniqueLocation {
String message() default "must be unique!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这并不引人注目,实际上它几乎是逐字复制自hibernate documentation.
我继续创建我的UniqueLocationValidator,并在其中使用持久性上下文时遇到了问题.我想进行防御性选择,因此尝试在我的应用程序中注入@Produces @PersistenceContext EntityManager.
为此,我包括了JBoss Seam,以使用它的InjectingConstraintValidatorFactory来配置我的validate.xml,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">
<constraint-validator-factory>
org.jboss.seam.validation.InjectingConstraintValidatorFactory
</constraint-validator-factory>
</validation-config>
在遇到Creating Constraint Violations的一些问题后,这就是我的验证器的实际外观:
@ManagedBean
public class UniqueLocationValidator implements
ConstraintValidator<UniqueLocation, Location> {
// must not return a result for name-equality on the same Id
private final String QUERY_STRING = "SELECT * FROM Location WHERE locationName = :value AND id <> :id";
@Inject
EntityManager entityManager;
private String constraintViolationMessage;
@Override
public void initialize(final UniqueLocation annotation) {
constraintViolationMessage = annotation.message();
}
@Override
public boolean isValid(final Location instance,
final ConstraintValidatorContext context) {
if (instance == null) {
// Recommended, instead use explicit @NotNull Annotation for
// validating non-nullable instances
return true;
}
if (duplicateLocationExists(instance)) {
createConstraintViolations(context);
return false;
} else {
return true;
}
}
private void createConstraintViolations(
final ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(constraintViolationMessage)
.addNode("locationName").addConstraintViolation();
}
private boolean duplicateLocationExists(final Location location) {
final String checkedValue = location.getLocationName();
final long id = location.getId();
Query defensiveSelect = entityManager.createNativeQuery(QUERY_STRING)
.setParameter("value", checkedValue).setParameter("id", id);
return !defensiveSelect.getResultList().isEmpty();
}
}
对于我当前的配置,到现在真正的牛肉,问题太多了:
当我收到用户的操作后运行以下代码时,该方法运行良好,并正确地将重复的位置名称标记为无效..当locationName不重复时,持久化也很好.
public long add(@Valid final Location location) {
entityManager.persist(location);
return location.getId();
}
注意,这里的entityManager和UniqueLocationValidator中的entityManager都是通过Weld CDI从前面提到的@PersistenceContext EntityManager注入的.
以下是无效的:
public long update(@Valid final Location location){
entityManager.merge(location);
return location.getId();
}
调用此代码时,我得到了一个相对较短的堆栈跟踪,其根源为ConcurrentModificationException.
我既不知道为什么会这样,也不知道如何解决这个问题.我无处尝试显式地对我的应用程序进行多线程处理,因此应该由我用作应用程序服务器的JBoss 7.1.1-Final进行管理.
解决方法:
您尝试执行的操作无法通过EntityManager进行.好吧,不是正常的.
在处理更新期间,将调用您的验证程序.通过EntityManager发送的查询会影响内部存储,即EntityManager的ActionQueue.这就是导致ConcurrentModificationException的原因:查询的结果会更改刷新更改时EntityManager正在迭代的列表.
一种解决方法是绕过EntityManager.
我们应该怎么做?
嗯,这有点脏,因为您实际上在对休眠实现添加了依赖关系,但是您可以通过各种方式来实现get the connection from the Session or EntityManager.而且,一旦有了java.sql.Connection对象,就可以使用PreparedStatement之类的东西来执行查询.
修复示例:
Session session = entityManager.unwrap(Session.class);
SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider connectionProvider = sessionFactoryImplementation.getConnectionProvider();
try {
connection = connectionProvider.getConnection();
PreparedStatement ps = connection.prepareStatement("SELECT 1 FROM Location WHERE id <> ? AND locationName = ?");
ps.setLong(1, id);
ps.setString(2, checkedValue);
ResultSet rs = ps.executeQuery();
boolean result = rs.next();//found any results? if we can retrieve a row: yes!
rs.close();
return result;
}//catch SQLException etc...
//finally, close resources (only the resultset!)
内容总结
以上是互联网集市为您收集整理的java-自定义验证注释引入了ConcurrentModificationException全部内容,希望文章能够帮你解决java-自定义验证注释引入了ConcurrentModificationException所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。