问题描述
该想法基本上是为了扩展具有自定义功能的 some 存储库.所以我得到了这个设置,它可以工作!
The idea is basically to extend some Repositories with custom functionality. So I got this setup, which DOES work!
@MappedSuperclass
abstract class MyBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Int = 0
var eid: Int = 0
}
interface MyRepository<T : MyBaseEntity> {
@Transactional
fun saveInsert(entity: T): Optional<T>
}
open class MyRepositoryImpl<T : MyBaseEntity> : MyRepository<T> {
@Autowired
private lateinit var entityManager: EntityManager
@Transactional
override fun saveInsert(entity: T): Optional<T> {
// lock table
entityManager.createNativeQuery("LOCK TABLE myTable WRITE").executeUpdate()
// get current max EID
val result = entityManager.createNativeQuery("SELECT MAX(eid) FROM myTable LIMIT 1").singleResult as? Int ?: 0
// set entities EID with incremented result
entity.eid = result + 1
// test if table is locked. sending manually 2-3 POST requests to REST
Thread.sleep(5000)
// save
entityManager.persist(entity)
// unlock
entityManager.createNativeQuery("UNLOCK TABLES").executeUpdate()
return Optional.of(entity)
}
}
我该如何像春季一样?
起初,我以为@Transactional
会执行LOCK和UNLOCK任务.我尝试了几个其他参数和@Lock
.我确实阅读了文档和一些教程,但是抽象的技术英语通常不容易理解.最后,我没有一个可行的解决方案,所以我手动添加了表锁定,效果很好.仍然希望采用一种更像弹簧的方式.
At first, I thought the @Transactional
would do the LOCK and UNLOCK stuff. I tried a couple of additional parameters and @Lock
. I did go through docs and some tutorials but the abstract technical English is often not easy to understand. At the end, I did not get a working solution so I manually added the table-locking, which works fine. Still would prefer a more spring-like way to do it.
推荐答案
1)您当前的设计也可能有问题. persist
不会立即在数据库中插入一行.当方法返回时,在事务提交时会发生这种情况.
1) There might be a problem with your current design as well. The persist
does not instantly INSERT a row in the database. That happens on transaction commit when the method returns.
因此您可以在实际插入之前解锁表:
So you unlock the table before the actual insert:
// save
entityManager.persist(entity) // -> There is no INSERT at this point.
// unlock
entityManager.createNativeQuery("UNLOCK TABLES").executeUpdate()
2)返回到仅使用不带本机的JPA的操作方法(由于默认情况下不支持,因此仍需要一些解决方法):
2) Going back to how to do it only with JPA without natives (it still requires a bit of a workaround as it is not supported by default):
// lock table by loading one existing entity and setting the LockModeType
Entity lockedEntity = entityManager.find(Entity.class, 1, LockModeType.PESSIMISTIC_WRITE);
// get current max EID, TRY NOT TO USE NATIVE QUERY HERE
// set entities EID with incremented result
// save
entityManager.persist(entity)
entityManager.flush() // -> Force an actual INSERT
// unlock by passing the previous entity
entityManager.lock(lockedEntity, LockModeType.NONE)
这篇关于如何锁定表...做些什么...用Spring Boot解锁表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!