微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring存储库找不到“ findBy *”方法,并将事务标记为回滚,从而导致持久性失败 实体存储库依赖项测试错误消息

如何解决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 举报,一经查实,本站将立刻删除。