当我们使用EclipseLink为JPA实体使用静态编织时,我们的应用程序中就会出现异常。
该应用程序是一个web应用程序,使用SpringDataJPA和SpringDataRESTWebMVC提供CRUD功能来更改实体。
当实体类没有通过编织处理时,它就工作了。但一旦我们使用编织实体,我们就会得到:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON:
Conflicting getter definitions for property "rootParentDescriptor":
org.eclipse.persistence.descriptors.InheritancePolicy#isRootParentDescriptor(0 params) vs org.eclipse.persistence.descriptors.InheritancePolicy#getRootParentDescriptor(0 params) (through reference chain: org.springframework.hateoas.Resources["content"]->java.util.UnmodifiableCollection[0]->org.eclipse.persistence.internal.descriptors.changetracking.AttributeChangeListener["descriptor"]->org.eclipse.persistence.descriptors.RelationalDescriptor["inheritancePolicy"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Conflicting getter definitions for property "rootParentDescriptor": org.eclipse.persistence.descriptors.InheritancePolicy#isRootParentDescriptor(0 params) vs org.eclipse.persistence.descriptors.InheritancePolicy#getRootParentDescriptor(0 params) (through reference chain: org.springframework.hateoas.Resources["content"]->java.util.UnmodifiableCollection[0]->org.eclipse.persistence.internal.descriptors.changetracking.AttributeChangeListener["descriptor"]->org.eclipse.persistence.descriptors.RelationalDescriptor["inheritancePolicy"])
..
Caused by: java.lang.IllegalArgumentException: Conflicting getter definitions for property "rootParentDescriptor": org.eclipse.persistence.descriptors.InheritancePolicy#isRootParentDescriptor(0 params) vs org.eclipse.persistence.descriptors.InheritancePolicy#getRootParentDescriptor(0 params)
at com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder.getGetter(POJOPropertyBuilder.java:190) ~[jackson-databind-2.2.2.jar:2.2.2]
当JSON响应应包含一个实体时,就会发生这种情况。实体非常简单,只有两个属性,没有关联等。
以下是使用的版本:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>1.1.0.M1</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.2</version>
</dependency>
是否有支持这种组合的配置或描述这种问题的已知问题?
我将JPA@Transient
注释属性视为Transient now,从而解决了这个问题。因此,只要您的持久性提供程序正确地使用了这些,您就可以了。如果不行,我们就得开罚单。
Spring数据JPA的1.3.5和1.4 RC1中将提供该修复程序。
经过一些研究,我找到了一个解决办法,但也许有人知道一个更好的解决办法。原因是,SpringDataCommons中的类JpaMetamodelMappingContext在编织过程中添加的实体类中找到了变量。它在元模型(JpaPersistentEntity)中收集它们作为属性,尽管这些字段只对EclipseLink的内部行为感兴趣。
我用自己的子类替换了JpaMetamodelMappingContext,这样就不会收集这些字段(比如@Transient)。这是用黑客手段完成的。
在spring配置中,我们向jpa:repositories添加了一个工厂类
<jpa:repositories base-package="de.viaboxx.vplan.database.dao"
entity-manager-factory-ref="entityManagerFactory"
factory-class="de.viaboxx.springframework.data.jpa.EclipseJpaRepositoryFactoryBean"/>
新的类Eclipse JpaRepositoryFactoryBean引入了JpaMetamodelMappingContext的新实现。这是源代码:(类从JpaRepositoryFactoryBean复制,在setEntityManager()中进行了更改)
public class EclipseJpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends
TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
private EntityManager entityManager;
/**
* The {@link EntityManager} to be used.
*
* @param entityManager the entityManager to set
*/
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
setMappingContext(
new EclipseJpaMetamodelMappingContext(entityManager.getMetamodel())); // <<-- this is the only change
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.
* TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport doCreateRepositoryFactory() {
return createRepositoryFactory(entityManager);
}
/**
* Returns a {@link RepositoryFactorySupport}.
*
* @param entityManager
* @return
*/
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new JpaRepositoryFactory(entityManager);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
Assert.notNull(entityManager, "EntityManager must not be null!");
super.afterPropertiesSet();
}
}
过滤内部属性的Hack包含在类Eclipse JpaMetamodelMappingContext中(包必须是org.springframework.data.jpa.mapping才能访问类JpaPeristentEntityImpl!)
public class EclipseJpaMetamodelMappingContext extends JpaMetamodelMappingContext {
/**
* Creates a new JPA {@link javax.persistence.metamodel.Metamodel} based {@link org.springframework.data.mapping.context.MappingContext}.
*
* @param model must not be {@literal null}.
*/
public EclipseJpaMetamodelMappingContext(Metamodel model) {
super(model);
}
@Override
protected JpaPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
JpaPersistentEntityImpl<?> owner,
SimpleTypeHolder simpleTypeHolder) {
// HACK: ignore fields added by eclipselink weaving
// because they cause problems during JSON marshaling with spring-data-rest 1.1.0.M1
if (field.getType().getName().startsWith("org.eclipse.") ||
field.getType().equals(PropertyChangeListener.class)) {
return new TransientPropertyToBeIgnored(field, descriptor, owner, simpleTypeHolder);
} else {
return super.createPersistentProperty(field, descriptor, owner, simpleTypeHolder); // call super!
}
}
static class TransientPropertyToBeIgnored extends AnnotationBasedPersistentProperty<JpaPersistentProperty>
implements JpaPersistentProperty {
@Override
public boolean isTransient() {
return true; // this causes the property to be ignored!
}
public TransientPropertyToBeIgnored(Field field, PropertyDescriptor propertyDescriptor,
PersistentEntity owner,
SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
}
@Override
protected Association createAssociation() {
return new Association<JpaPersistentProperty>(this, null);
}
}
}
无论编织或未编织的实体如何,这都适用于我们。
使用Hibernate而不是EclipseLink时不会出现问题,但是使用Hibernate需要jackson Hibernate模块和其他配置更改。
我有两个实体类它只有一个字段叫做和第二个实体它有两个字段和。数据库结构 我正在创建一个简单的CRUD web-app,但是update方法不是更新实体,而是在DB中插入新值。我检查了一下,当用户点击指定菜单上的更新时,第一个实体的id和它的配料id也会被预先定义。我是spring boot和thymeleaf的新手,不知道当您有一个以上的实体时如何使用JPA。 菜单实体: 配料实体: 控制器(仅更
问题内容: 我开始使用Spring Data JPA在Spring Boot应用程序上进行工作,以在用户和角色之间建立ManyToMany关系。 此关系在User类中定义如下: 我使用以下角色创建角色: 之后向用户分配角色失败: 引发以下异常(为便于阅读而设置格式): 但是,如果在创建关系之前保存了用户,则可以正常工作: 我不得不两次保存/更新用户似乎有些不合理。有什么方法可以在不先保存 用户的
我已经尝试使用Spring Boot+Spring Data JPA更新实体很久了。我得到所有正确的观点回到我。我的编辑视图按ID向我返回正确的实体。一切进展顺利。直到我实际尝试保存/合并/持久化对象。每次我拿回一个有新ID的新实体。我只是不知道为什么。我看了网上的例子,还有你可能会参考的重复问题的链接。那么,在这些代码中,我在哪里犯了错误呢? 在这段代码之后。我的视图将我返回到正确的URL,但I
我在从数据库中删除实体时遇到问题。不管我做什么,它都不会删除。 驾驶员等级 评级等级 我做的第一件事是用,当调用时,它会抛出: org.postgresql.util。PSQLException:错误:更新或删除表“drivers”违反了表“ratings”上的外键约束“fk3raf3d9ucm571r485t8e7ew83” 好吧,选择另一种方式。尝试使用删除每个评级对象,但从未发生过,它只是彻
我有一个测试用例,需要将100,000个实体实例持久化到数据库中。我当前使用的代码就是这样做的,但直到将所有数据持久化到数据库中为止,最多需要40秒。数据是从一个大约15 MB大小的JSON文件中读取的。 现在,我已经为另一个项目在自定义存储库中实现了批处理插入方法。但是,在这种情况下,我有很多顶级实体要持久化,只有几个嵌套实体。 在我当前的例子中,我有5个实体,这些实体包含大约30个实体的列表。