Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate @Transactional如何在测试方法上工作?_Hibernate_Jpa_Junit_Transactions_Jta - Fatal编程技术网

Hibernate @Transactional如何在测试方法上工作?

Hibernate @Transactional如何在测试方法上工作?,hibernate,jpa,junit,transactions,jta,Hibernate,Jpa,Junit,Transactions,Jta,我想知道@Transactional如何在测试方法上与Spring数据JPA/Hibernate一起工作。我在网上搜索了一些解释,但似乎还是不太清楚 下面是我正在使用的代码: Member.java 问题是,当我单独使用@Transactional而不使用@Commit时,只会创建用户和角色条目。表MEMBER\u ROLE已创建但为空(无条目):未保存n:n@ManyToMany单向关系 使用@Commit时,一切正常:有两个条目对应于John Doe用户的角色 以下是我的问题: cru

我想知道@Transactional如何在测试方法上与Spring数据JPA/Hibernate一起工作。我在网上搜索了一些解释,但似乎还是不太清楚

下面是我正在使用的代码:

Member.java
  • 问题是,当我单独使用@Transactional而不使用@Commit时,只会创建用户和角色条目。表
    MEMBER\u ROLE
    已创建但为空(无条目):未保存
    n:n
    @ManyToMany单向关系
  • 使用
    @Commit
    时,一切正常:有两个条目对应于John Doe用户的角色
以下是我的问题:

crudepository.save(…)如何在@Transactional的后台工作,以及为什么单独使用此注释会执行“部分保存”?我们应该期望,如果没有
@Commit
就不会向数据库提交任何内容(所有内容都是回滚的)。

在测试方法上使用
@Transactional
是否是一种良好的做法?

Crudepository.save(…)如何在@Transactional的后台工作,以及为什么单独使用此注释会执行“部分保存”?我们应该预期,如果没有@Commit,就不会向数据库提交任何内容(并且所有内容都是回滚的)

由于它是一个测试,默认情况下,由于
TransactionalTestExecutionListener
,事务应该回滚。现在,您会问为什么会提交某些内容,这可能是因为内部事务
@Transactional
跨越整个测试方法的事务,因此如果您使用某些dao(如您的案例),该事务也将回滚,但是如果某些方法使用除
REQUIRED
之外的事务传播类型,例如
REQUIRED\u NEW
,则仍可以执行对db的调用,因为
REQUIRED\u NEW
暂停测试中的当前事务并创建一个新事务。新的一个将被承诺。由于hibernate缓存,还存在刷新时间问题——他在事务结束时(通常在方法结束时)调用db,因此在持久化元素后直接获取元素可能会失败。这两件事都很棘手

在测试方法上使用@Transactional是一种好的实践吗

当然,但不是为了测试事务边界。请记住,您还可以使用
@DataJpaTest
,它为每个测试方法放置
@Transactional

资料来源:


  • 我从来没有在测试方法上使用过Transaction,一直以来,我都是在服务类测试类中使用它,以正常的方式初始化数据,执行测试,并回滚数据更改,以提供测试数据集的原始数据,从而确保在每次测试用例运行后都不会修改任何数据。使下一个测试用例不会受到上一个测试用例的影响,并且每次测试都会以相同的结果运行。
    @Entity 
    @Table(name = "MEMBER")
    public class Member  {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        String firstname;
    
        String lastname;
    
        @ManyToMany(cascade = CascadeType.ALL)
        @JoinTable(
              name = "MEMBER_ROLE",
              joinColumns = @JoinColumn(name = "member_id"),
              inverseJoinColumns = @JoinColumn(name = "role_id")
        )
        private Set<Role> roles = new HashSet<Role>();
    
        // Getters...
        // Setters...
    
    }
    
    @Entity
    @Table(name = "ROLE")
    public class Role {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        private String name;
    
        private String description;
    
        public Role(String name, String description) {
    
            this.name = name;
            this.description = description;
        }
    
        @ManyToMany(mappedBy = "roles", cascade = CascadeType.ALL)
        private Set<User> users = new HashSet<User>();
    
        public void addUser(User user) {
            users.add(user);
            user.getRoles().add(this);
        }
    
        // Getters...
        // Setters...
    
    }
    
    @SpringBootTest
    public class MemberRepositoryTest {
    
        @Autowired
        private MemberRepository memberRepository;
    
    
        @Test
        @Transactional
        //@Commit // When @Commit is uncommented, the relation is saved in the database
        public void testSave() {
    
            Member testMember = new Member();
    
            testMember.setFirstname("John");
            testMember.setLastname("Doe");
    
            Role role1 = new Role("ROLE_USER", "The role of for basic users");
            Role role2 = new Role("ROLE_ADMIN", "The role of for admin users");
    
            testMember.getRoles().add(role1);
            testMember.getRoles().add(role2);
    
            this.memberRepository.save(testMember);
    
            // The 2 roles are well in the set
            System.out.println("********" + this.memberRepository.findById(1).get().getRoles().toString());
    
        }
    
    }