仅供参考:我已经检查并尝试了同一问题的其他问题下的解决方案
在我的应用程序(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;
}
}
}
暂无答案!
目前还没有任何答案,快来回答吧!