在jpa的单元测试中,丢弃会话/entitymanager是关闭的错误

a14dhokn  于 2021-07-06  发布在  Java
关注(0)|答案(0)|浏览(277)

仅供参考:我已经检查并尝试了同一问题的其他问题下的解决方案
在我的应用程序(vaadin+springboot+hibernate)中,我需要测试一个用例的并发问题。为了测试这一点,我需要以下设置:
我有一个repository类,用于使用jpa写入数据库。
我创建不同的线程(模拟不同的用户)。
不同的用户应该使用相同的存储库示例。4) 每个线程(用户)都应该尝试写入数据库。
这样我就可以看到存储库类中的实体管理器的行为。
如果我运行下面的代码,它有时会很好地写入数据库,但大多数时候,它会给出实体管理器/会话是一个关闭的异常。
我不明白为什么有时有用,有时不行?我怎样才能解决这个问题?

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApplication.class)
@Transactional(rollbackFor=Exception.class)
@ContextConfiguration(classes = ShouldNotFailWithConcurrentOperation.class)
@Rollback
public class ShouldNotFailWithConcurrentOperation {

private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private EmailRepository emailRepository;

public ShouldNotFailWithConcurrentOperation() {
    // TODO Auto-generated constructor stub
}

@Before
public void setUp() throws Exception {
    System.setProperty("spring.datasource.driver-class-name",
            "com.microsoft.sqlserver.jdbc.SQLServerDriver");
    System.setProperty("spring.jpa.properties.hibernate.format_sql", "true");
    System.setProperty("spring.jpa.properties.hibernate.dialect",
            "org.hibernate.dialect.SQLServer2012Dialect");
    System.setProperty("spring.jpa.hibernate.ddl-auto", "update");
    System.setProperty("spring.datasource.url", SettingsResolver
            .getInstance().getSetting("database.server.connection.url"));
    System.setProperty("spring.datasource.username", SettingsResolver
            .getInstance().getSetting("database.server.user.name"));
    try {
        System.setProperty("spring.datasource.password", Encrypter
                .decrypt(SettingsResolver.getInstance().getSetting(
                        "database.server.user.password")));
    } catch (Exception e) {
        logger.error(
                "Error occured while trying to decrypt database connection password: ",
                e);
    }
}

@Test
public void test() {

    Thread thread1 = new Thread("thread1") {
        public void run() {
            System.out.println("hello from thread1");

            EmailContact contact = new EmailContact();

            contact.setUsername("user1" 
                    + "@gmail.com");
            contact.setContactName("contact2");
            contact.setContactDetail("detail1"
                    + "@gmail.com");
            try{
            getRepository().save(contact);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    };

    Thread thread2 = new Thread("thread2") {
        public void run() {
            System.out.println("hello from thread2");

            System.out.println(getRepository());
        }
    };

    Thread thread3 = new Thread("thread3") {
        public void run() {
            System.out.println("hello from thread3");

            System.out.println(getRepository());
        }
    };

    thread1.start();
 //     thread2.start();
 //     thread3.start();
}

public EmailRepository getRepository() {
    return this.emailRepository;
}
}

我的存储库类如下

@Repository
@Transactional
public class EmailRepository {

private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
EntityManager emailRepository;

public EmailContact save(EmailContact contactEntity) {

    System.out.println(this.emailRepository);

    try {
        if (!isTupleAlreadyExists(contactEntity)) {
            emailRepository.persist(contactEntity);
        }

    } catch (Exception e) {
        logger.error("Exception occured while trying to write to database table for email contact: "
                , e);
        throw e;
    }

    return contactEntity;
}

public boolean isTupleAlreadyExists(EmailContact contactEmail) {
    try {
        TypedQuery<EmailContact> query = emailRepository
                .createQuery(
                        "SELECT e FROM EmailContact e WHERE e.userName = :userName AND e.contactName = :contactName AND e.contactDetail = :contactMail",
                        EmailContact.class);

        List<EmailContact> duplicationContactList = query
                .setParameter("userName", contactEmail.getUsername())
                .setParameter("contactName", contactEmail.getContactName())
                .setParameter("contactMail",
                        contactEmail.getContactDetail()).getResultList();

        return (!duplicationContactList.isEmpty());
    } catch (Exception e) {
        logger.error("Exception occured while trying to query for an existing tuple: ", e);
        return false;
    }
}
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题