在persist()操作期间,EclipsLink似乎不检测或激发基类中的JSR303注释约束,基类是实体的映射超类。
public Base
{
@NotNull
private Integer id;
private String recordName;
//other stuff (getters etc)
}
public class MyObject
extends Base
{
//stuff...
}
<mapped-superclass class="Base">
<attributes>
<basic name="recordName">
<column name = "NAME" />
</basic>
</attributes>
</mapped-superclass>
最后:
<entity class="MyObject">
<table name="TheTable"/>
<attributes>
<id name="id">
<column name="recordId" />
</id>
</attributes>
</entity>
其他一些相关参数:
据我所见,eclipse Link2.6.x到2.6.4在维护触发JSR303 bean验证的契约方面似乎有一个巨大的bug。目前,Eclipselink2.6.4仅在子实体被右向外标记为约束时才触发这些验证。
我有在JEE6库版本(例如eclipselink 2.4.x)下完美工作的集成测试。
当我将库升级到JEE7 verions时,在ecliselink的特殊情况下,这意味着版本:2.6.1到2.6.4,它们都表现出相同的bug。
这足以调用验证器(例如,hibernate验证器)。
在本例中,我的the测试仍然失败,因为现在我得到了两个@NotNull约束验证,而不是一个。
在下面的代码片段中,我将说明Eclipselink2.6.1上堆栈跟踪的相关chucnk。
Caused by: javax.validation.ConstraintViolationException:
Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'.
Please refer to embedded ConstraintViolations for details.
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:108)
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.prePersist(BeanValidationListener.java:77)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:748)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyEJB30Listeners(DescriptorEventManager.java:691)
at org.eclipse.persistence.descriptors.DescriptorEventManager.executeEvent(DescriptorEventManager.java:229)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectClone(UnitOfWorkImpl.java:4314)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4291)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:521)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4233)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:507)
at TEST_THAT_IS_PROBLEMATIC
... 25 more
eclipselink中的bug似乎是当BeanValidationListener询问BeanValidationHelper某个类是否受到约束时出现的:
来自Eclipselink的代码如下:
private void validateOnCallbackEvent(DescriptorEvent event, String callbackEventName, Class[] validationGroup) {
Object source = event.getSource();
boolean noOptimization = "true".equalsIgnoreCase((String) event.getSession().getProperty(PersistenceUnitProperties.BEAN_VALIDATION_NO_OPTIMISATION));
boolean shouldValidate = noOptimization || beanValidationHelper.isConstrained(source.getClass());
if (shouldValidate) {
Set<ConstraintViolation<Object>> constraintViolations = getValidator(event).validate(source, validationGroup);
if (constraintViolations.size() > 0) {
// There were errors while call to validate above.
// Throw a ConstrainViolationException as required by the spec.
// The transaction would be rolled back automatically
// TODO need to I18N this.
throw new ConstraintViolationException(
"Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'" +
callbackEventName + "'. Please refer to embedded ConstraintViolations for details.",
(Set<ConstraintViolation<?>>) (Object) constraintViolations); /* Do not remove the explicit
cast. This issue is related to capture#a not being instance of capture#b. */
}
}
}
问题是查询:
beanValidationHelper.isConstrained(source.getClass());
private Boolean detectConstraints(Class<?> clazz) {
for (Field f : ReflectionUtils.getDeclaredFields(clazz)) {
for (Annotation a : f.getDeclaredAnnotations()) {
final Class<? extends Annotation> type = a.annotationType();
if (KNOWN_CONSTRAINTS.contains(type.getName())){
return true;
}
// Check for custom annotations on the field (+ check inheritance on class annotations).
// Custom bean validation annotation is defined by having @Constraint annotation on its class.
for (Annotation typesClassAnnotation : type.getAnnotations()) {
final Class<? extends Annotation> classAnnotationType = typesClassAnnotation.annotationType();
if (Constraint.class == classAnnotationType) {
KNOWN_CONSTRAINTS.add(type.getName());
return true;
}
}
}
}
Field f : ReflectionUtils.getDeclaredFields(clazz)
只返回当前类的字段,而不返回父类。
与此同时,我强迫自己做的是,在BeanValidationHelper中设置一个变通方法,以便将坏掉的算法用于检测需要验证的类:
@Transient
@NotNull
private final char waitForEclipseLinkToFixTheVersion264 = 'a';
通过上述操作,您的代码可以用一个块清晰地标记出来,将来可以删除该块。因为场是瞬态的...嘿,它不会改变你的分贝。
这方面的解决办法,我还不确定。我将研究如何在PreInserPhase期间注册一个事件listner,它的作用与BeanValidationListner相同。或者,我将在本地修补BeanValidationListner.class以订阅PreINsert事件。
我不喜欢修改其他人维护的库代码,所以我将首先使用我们自己的eventListner作为这个bug的临时工作人员。
添加允许验证这两个bug的存储库。https://github.com/99sono/eclipselink_2_6_4_jsr_303bug
package jpa.eclipselink.test.bug2workaround;
import java.util.Map;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy;
import org.eclipse.persistence.internal.jpa.deployment.BeanValidationInitializationHelper;
import org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener;
/**
* Temporary work-around for JSR 303 bean validation flow in eclipselink.
*
* <P>
* Problem: <br>
* The
* {@link DeferredChangeDetectionPolicy#calculateChanges(Object, Object, boolean, org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet, org.eclipse.persistence.internal.sessions.UnitOfWorkImpl, org.eclipse.persistence.descriptors.ClassDescriptor, boolean)}
* during a flush will do one of the following: <br>
* {@code descriptor.getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery)); }
* or <br>
*
* {@code descriptor.getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreUpdateEvent, writeQuery)); }
*
* <P>
* WHe it does
* {@code descriptor.getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery)); }
* the {@link BeanValidationListener} will not do anything. We want it to do bean validation.
*/
public class ForceBeanManagerValidationOnPreInsert extends DescriptorEventAdapter {
private static final Class[] DUMMY_GROUP_PARAMETER = null;
/**
* This is is the EJB validator that eclipselink uses to do JSR 303 validations during pre-update, pre-delete,
* pre-persist, but not pre-insert.
*
* Do not access this field directly. Use the {@link #getBeanValidationListener(DescriptorEvent)} api to get it, as
* this api will initialize the tool if necessary.
*/
BeanValidationListener beanValidationListener = null;
final Object beanValidationListenerLock = new Object();
/**
*
*/
public ForceBeanManagerValidationOnPreInsert() {
super();
}
/**
* As a work-around we want to do bean validation that the container is currently not doing.
*/
@Override
public void preInsert(DescriptorEvent event) {
// (a) get for ourselves an instances of the eclipse link " Step 4 - Notify internal listeners."
// that knows how to run JSR 303 validations on beans associated to descriptor events
BeanValidationListener eclipseLinkBeanValidationListenerTool = getBeanValidationListener(event);
// (b) let the validation listener run its pre-update logic on a preInsert it serves our purpose
eclipseLinkBeanValidationListenerTool.preUpdate(event);
}
/**
* Returns the BeanValidationListener that knows how to do JSR 303 validation. Creates a new instance if needed,
* otherwise return the already created listener.
*
* <P>
* We can only initialize our {@link BeanValidationListener} during runtime, to get access to the JPA persistence
* unit properties. (e.g. to the validation factory).
*
* @param event
* This event describes an ongoing insert, updetae, delete event on an entity and for which we may want
* to force eclipselink to kill the transaction if a JSR bean validation fails.
* @return the BeanValidationListener that knows how to do JSR 303 validation.
*/
protected BeanValidationListener getBeanValidationListener(DescriptorEvent event) {
synchronized (beanValidationListenerLock) {
// (a) initializae our BeanValidationListener if needed
boolean initializationNeeded = beanValidationListener == null;
if (initializationNeeded) {
beanValidationListener = createBeanValidationListener(event);
}
// (b) return the validation listerner that is normally used by eclipse link
// for pre-persist, pre-update and pre-delete so that we can force it run on pre-insert
return beanValidationListener;
}
}
/**
* Creates a new instance of the {@link BeanValidationListener} that comes with eclipse link.
*
* @param event
* the ongoing db event (e.g. pre-insert) where we want to trigger JSR 303 bean validation.
*
* @return A new a new instance of the {@link BeanValidationListener} .
*/
protected BeanValidationListener createBeanValidationListener(DescriptorEvent event) {
Map peristenceUnitProperties = event.getSession().getProperties();
ValidatorFactory validatorFactory = getValidatorFactory(peristenceUnitProperties);
return new BeanValidationListener(validatorFactory, DUMMY_GROUP_PARAMETER, DUMMY_GROUP_PARAMETER,
DUMMY_GROUP_PARAMETER);
}
/**
* Snippet of code taken out of {@link BeanValidationInitializationHelper}
*
* @param puProperties
* the persistence unit properties that may be specifying the JSR 303 validation factory.
* @return the validation factory that can check if a bean is violating business rules. Almost everyone uses
* hirbernate JSR 303 validation.
*/
protected ValidatorFactory getValidatorFactory(Map puProperties) {
ValidatorFactory validatorFactory = (ValidatorFactory) puProperties
.get(PersistenceUnitProperties.VALIDATOR_FACTORY);
if (validatorFactory == null) {
validatorFactory = Validation.buildDefaultValidatorFactory();
}
return validatorFactory;
}
}
下面是一个具有解决方案的实体的示例。
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DESCRIMINATOR", length = 32)
@DiscriminatorValue("Bug2WorkAround")
@Entity
@EntityListeners({ ForceBeanManagerValidationOnPreInsert.class })
public class Bug2Entity2WithWorkAround extends GenericEntity {
亲切的问候。
问题内容: 我们有一个有一些特殊要求的项目,其中之一是从Oracle 10g数据库的XMLType数据库列中获取数据。 我们已经找到了使用JDBC的简单解决方案,但是由于所有数据访问都是通过JPA(使用的实现是EclipseLink)来完成,因此它会使应用程序有些混乱。 我们已经进行了一些研究,找到了一些解决方案,例如使用Converters和其他辅助类型,但是实现似乎有些复杂。 因此,我的问题是
假设中间CNN层的输入大小为512×512×128,在卷积层中,我们在步长2处应用48个7×7滤波器,没有填充。我想知道结果激活图的大小是多少?
关于MapStruct的问题。我有这样的情况,我从基实体扩展类,但不知道如何映射它。这是我的箱子。 BaseEntity: 基础: 没有显示错误,在映射器实现(生成的代码)中没有该ID的映射:
主要内容:1. 一对一,2. 一对多,3. 多对一,4. 多对多映射约束 映射约束是一种数据约束,表示通过关系集可以与另一个实体相关的实体的数量。 它在描述涉及两个以上实体集的关系集时最有用。 对于实体集A和B上的二元关系集R,有四种可能的映射基数。这些如下: 一对一(1:1) 一对多(1:M) 多对一(M:1) 多对多(M:M) 1. 一对一 在一对一映射中,E1中的实体与E2中的至多一个实体相关联,并且E2中的实体与E1中的至多一个实体相关联。 2. 一对
<![CDATA[插入MEMBER_SERVICE_RECORD(MEMBER_ID,SERVICE_DATE,service_milees,SERVICE_DESC,MODIFIED_DATE)值(?,?,?,?,?)]]>
问题内容: 通用实体,超类: pojo: 我尝试使用那些注释:@ AttributeOverride,@ Id等,但是它不起作用。你能帮助我吗?我想覆盖属性“ id”以通过pojo / table指定另一个列名和一个序列。最好的方法是什么? 问题答案: 试试这个,代替