如何解决Spring存储库找不到“ findBy *”方法,并将事务标记为回滚,从而导致持久性失败 实体存储库依赖项测试错误消息
相关代码
实体
@Data
@Entity
@Table(name = "SOME_FEATURE")
@SequenceGenerator(name = "FEATURE_SEQ",sequenceName = "SOME_FEATURE_SEQ",allocationSize = 1)
@EqualsAndHashCode(exclude = {"featuredItems"})
@ToString(exclude = {"featuredItems"})
public class SomeFeatureEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SOME_FEATURE_SEQ")
private Long id;
@Temporal(TemporalType.TIMESTAMP)
@Generated(GenerationTime.INSERT)
private Date created;
private String name;
private String featureType = "Text";
@Column(name = "feature_description")
private String description;
@OnetoMany(mappedBy = "feature")
@Setter(AccessLevel.NONE)
private Set<SubFeatureEntity> featuredItems;
public Set<SubFeatureEntity> getFeaturedItems() {
return Collections.unmodifiableSet(featuredItems);
}
@Temporal(TemporalType.TIMESTAMP)
@Generated(GenerationTime.ALWAYS)
private Date modified;
}
存储库
@Repository
public interface SomeFeatureEntityRepository extends JpaRepository<SomeFeatureEntity,Long>{
SomeFeatureEntity findByName(String name);
}
依赖项
我无法控制版本,无法升级
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Ingalls-SR20</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.23.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
测试
这已经被消毒了,因为我不会因为暴露IP而被bean计数器大喊大叫-我的双手被绑在这里。
@Transactional
@Test
public void testFindByFeaturesName() {
assertTrue(TestTransaction.isActive());
FeatureEntity featureEntity;
featureEntity = featureEntityRepository.findByName(TEST_FEATURE);
FeatureManyRelationEntity FeatureManyRelationEntity = new FeatureManyRelationEntity();
FeatureManyRelationEntity.setCreated(Now);
FeatureManyRelationEntity.setFeatures(featureManyRelationEntity);
FeatureManyRelationEntity.setFeature(featureEntity);
// This assertion passes - must be a different transaction
assertTrue(TestTransaction.isActive());
FeatureManyRelationEntityRepository.saveAndFlush(FeatureManyRelationEntity);
// This assertion is never executed the flush above does not bother to execute.
assertTrue(TestTransaction.isActive());
Set<FeatureManyRelationEntity> featuresFeatures = FeatureManyRelationEntityRepository.findByFeatures(featureManyRelationEntity);
assertNotNull(featuresFeatures);
assertEquals(1,featuresFeatures.size());
for (FeatureManyRelationEntity e : featuresFeatures) {
assertEquals(TEST_FEATURE,e.getFeature().getName());
assertEquals(TEST_Features_ITEM,e.getFeatures().getName());
}
}
错误消息
> 2020-08-25 13:51:04,471 [main] DEBUG o.s.d.j.r.query.JpaQueryFactory - Looking up query for method findByName
2020-08-25 13:51:04,472 [main] DEBUG o.s.d.j.repository.query.NamedQuery - Looking up named query SomeFeatureEntity.findByName
2020-08-25 13:51:04,472 [main] DEBUG o.h.j.spi.AbstractEntityManagerImpl - Mark transaction for rollback
2020-08-25 13:51:04,472 [main] DEBUG o.s.d.j.repository.query.NamedQuery - Did not find named query SomeFeatureEntity.findByName
> Note that the transaction is doomed to fail above even before the test starts
The folloing logs show that there is no problem actually `running` the findByName method
>2020-08-25 13:51:06,681 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@55f26df5] for key [public abstract com.myCompany.myDepartment.product.storage.impl.repository.entity.someFeatureEntity com.myCompany.myDepartment.product.storage.impl.repository.someFeatureEntityRepository.findByName(java.lang.String)] to thread [main]
2020-08-25 13:51:06,681 [main] TRACE o.s.t.i.TransactionInterceptor - Don't need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByName]: This method isn't transactional.
2020-08-25 13:51:06,681 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@641312f] for key [org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean@90181ca] bound to thread [main]
2020-08-25 13:51:06,681 [main] DEBUG o.h.jpa.criteria.CriteriaQueryImpl - Rendered criteria query -> select generatedalias0 from SomeFeatureEntity as generatedalias0 where generatedalias0.name=:name
2020-08-25 13:51:06,684 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@641312f] for key [org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean@90181ca] bound to thread [main]
Hibernate: select Somefeatureent0_.id as id1_3_,Somefeatureent0_.created as created2_3_,Somefeatureent0_.somefeature_description as Somefeature_3_3_,Somefeatureent0_.somefeature_type as Somefeature_4_3_,Somefeatureent0_.modified as modified5_3_,Somefeatureent0_.name as name6_3_ from ec_Somefeature Somefeatureent0_ where Somefeatureent0_.name=?
2020-08-25 13:51:06,685 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0
2020-08-25 13:51:06,685 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.myCompany.myDepartment.product.storage.impl.repository.entity.someFeatureEntity#7]
2020-08-25 13:51:06,686 [main] DEBUG o.h.engine.internal.TwoPhaseLoad - Resolving associations for [com.myCompany.myDepartment.product.storage.impl.repository.entity.someFeatureEntity#7]
2020-08-25 13:51:06,686 [main] DEBUG o.h.engine.internal.TwoPhaseLoad - Done materializing entity [com.myCompany.myDepartment.product.storage.impl.repository.entity.someFeatureEntity#7]
2020-08-25 13:51:06,686 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@55f26df5] for key [public abstract com.myCompany.myDepartment.product.storage.impl.repository.entity.someFeatureEntity com.myCompany.myDepartment.product.storage.impl.repository.someFeatureEntityRepository.findByName(java.lang.String)] from thread [main]
到目前为止,一切都很好,因为还不需要实际的转账。
>2020-08-25 13:51:06,686 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@44653789] for key [public abstract java.lang.Object org.springframework.data.jpa.repository.JpaRepository.saveAndFlush(java.lang.Object)] to thread [main]
2020-08-25 13:51:06,690 [main] DEBUG o.s.b.f.s.DefaultListablebeanfactory - Returning cached instance of singleton bean 'transactionManager'
2020-08-25 13:51:06,691 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@6731203d] for key [org.hibernate.jpa.internal.EntityManagerFactoryImpl@67b95f82] bound to thread [main]
2020-08-25 13:51:06,691 [main] TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush]
2020-08-25 13:51:06,693 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@641312f] for key [org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean@90181ca] bound to thread [main]
Hibernate: call next value for SOME_FEATURE_SEQ
2020-08-25 13:51:06,700 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[16]]
2020-08-25 13:51:06,701 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 16,using strategy: org.hibernate.id.SequenceHiLoGenerator
2020-08-25 13:51:06,708 [main] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@641312f] for key [org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean@90181ca] bound to thread [main]
下面的错误(TransactionrequiredException)具有误导性。线程绑定了/有一个事务,它被标记为回滚,对于持久化没有用。
>2020-08-25 13:51:06,709 [main] TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush] after exception: javax.persistence.TransactionrequiredException: no transaction is in progress
这仅在持久存在时才引起问题。查找本身工作正常。 这里的问题不是没有命名查询。我知道没有。我希望Spring根据存储库方法的名称创建一个并继续。相反,它将事务标记为回滚,并且不会尝试最终持久化在其他实体上。 如果可以的话,请帮忙。
解决方法
我理解为其他用户建议使用CRUDRepository而不是JPA。
我可以看到多个错误。对于findByName(如果存在问题),在这种情况下,您的应用程序本身将无法启动,并且应用程序启动时会引发错误,指出没有包含name和all的属性。
对于 TransactionRequiredException
,您需要使用带有2属性的 @Transactional
注释进行管理。
此外,只需为 propagation
提供一些属性,例如 rollbackFor
和 @Transactional
注释。
还有一点要确保,您已经从此包 @org.springframework.transaction.annotation.Transactional
中导入了@Transactional。
@Transactional(readOnly = false,propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
@Test
public void testFindByFeaturesName() {
assertTrue(TestTransaction.isActive());
FeatureEntity featureEntity;
featureEntity = featureEntityRepository.findByName(TEST_FEATURE);
FeatureManyRelationEntity FeatureManyRelationEntity = new FeatureManyRelationEntity();
FeatureManyRelationEntity.setCreated(now);
FeatureManyRelationEntity.setFeatures(featureManyRelationEntity);
FeatureManyRelationEntity.setFeature(featureEntity);
// This assertion passes - must be a different transaction
assertTrue(TestTransaction.isActive());
FeatureManyRelationEntityRepository.saveAndFlush(FeatureManyRelationEntity);
// This assertion is never executed the flush above does not bother to execute.
assertTrue(TestTransaction.isActive());
Set<FeatureManyRelationEntity> featuresFeatures = FeatureManyRelationEntityRepository.findByFeatures(featureManyRelationEntity);
assertNotNull(featuresFeatures);
assertEquals(1,featuresFeatures.size());
for (FeatureManyRelationEntity e : featuresFeatures) {
assertEquals(TEST_FEATURE,e.getFeature().getName());
assertEquals(TEST_Features_ITEM,e.getFeatures().getName());
}
}
或者在最坏的情况下,您可以尝试从此方法中删除交易注释。
,使用findByName(String name)
时,使用CrudRepository将自动查询bij名称。
它将基于名称(您的实体的属性)进行查询。
我不确定JPA Repo是否会执行相同的操作,但是我使用的是Crud,这对我有用。也许JPA需要手动查询,而Crud不需要。
根据我对您的错误的了解,JPA没有对FindByName的查询:
2020-08-25 13:51:04,472 [main] DEBUG o.s.d.j.repository.query.NamedQuery - Did not find named query SomeFeatureEntity.findByName
Crud将为您提供查询,请尝试一下。
,感谢您的帮助。原来我的问题是接线错误。我不知道,我们给交易经理一个非托管实体经理。一旦我解决了该问题,代码便开始正常工作。该测试确实发现了一个真正的问题。事实证明,这与group
方法无关。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。