Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.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
Java 如何在spring数据jpa查询中指定@lock timeout?_Java_Spring_Oracle_Hibernate_Jpa - Fatal编程技术网

Java 如何在spring数据jpa查询中指定@lock timeout?

Java 如何在spring数据jpa查询中指定@lock timeout?,java,spring,oracle,hibernate,jpa,Java,Spring,Oracle,Hibernate,Jpa,如何指定查询的@Lock超时? 我正在使用Oracle11g,我希望我可以使用类似于“从表中选择id,其中id=?1用于更新等待5”的东西 我定义的方法如下: @Lock(LockModeType.PESSIMISTIC_WRITE) Stock findById(String id); 它似乎永远锁着。 当我在LocalContainerEntityManagerFactoryBean.jpapproperties中设置javax.persistence.lock.timeout=0时,没有

如何指定查询的
@Lock
超时? 我正在使用Oracle11g,我希望我可以使用类似于
“从表中选择id,其中id=?1用于更新等待5”的东西

我定义的方法如下:

@Lock(LockModeType.PESSIMISTIC_WRITE)
Stock findById(String id);
它似乎永远锁着。 当我在
LocalContainerEntityManagerFactoryBean.jpapproperties
中设置
javax.persistence.lock.timeout=0时,没有任何效果

要以悲观方式锁定实体,请将锁定模式设置为
悲观的读取
悲观的写入
,或
悲观力增量

如果无法获得悲观锁,但锁定失败 不会导致事务回滚,
LockTimeoutException
是 扔

持久性提供程序应使用的时间长度(以毫秒为单位) 可以使用指定等待获取数据库表上的锁 javax.persistence.lock.timeout属性。如果需要时间 获取的锁超过此属性的值
LockTimeoutException
将被抛出,但当前事务 将不会标记为回滚如果此属性设置为0,则 持久性提供程序应该抛出一个
LockTimeoutException
,如果 无法立即获得锁。

如果在多个位置设置了
javax.persistence.lock.timeout
,则 值将按以下顺序确定:

  • EntityManager
    查询方法之一的参数
  • @NamedQuery
    注释中的设置
  • Persistence.createEntityManagerFactory
    方法的参数
  • persistence.xml
    部署描述符中的值
  • 对于弹簧数据1.6或更高版本 从Spring Data JPA的1.6版开始,CRUD方法就支持
    @Lock
    (事实上,已经有了可用的)。有关更多详细信息,请参见此

    对于该版本,您只需声明以下内容:

    interface WidgetRepository extends Repository<Widget, Long> {
    
      @Lock(LockModeType.PESSIMISTIC_WRITE)
      Widget findOne(Long id);
    }
    
    TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
    
    您可以创建一些静态锁管理器,它有一个
    ThreadLocal
    成员变量,然后在每个存储库中使用ThreadLocal中设置的锁模式调用bindResource的每个方法周围都有一个方面。这将允许您在每个线程的基础上设置锁定模式。然后,您可以创建自己的
    @MethodLockMode
    注释,该注释将在一个方面中包装该方法,该方面在运行该方法之前设置线程特定的锁定模式,并在运行该方法之后将其清除

    资源链接:

  • 悲观锁超时的各种示例 设置悲观锁 实体对象可以通过lock方法显式锁定:

    em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
    
    第一个参数是实体对象。第二个参数是请求的锁模式

    如果调用锁时没有活动事务,则会抛出
    TransactionRequiredException
    ,因为显式锁定需要活动事务

    如果无法授予所请求的悲观锁,则会引发
    LockTimeoutException

    • 如果另一个用户(即 由另一个EntityManager实例表示)当前持有
      悲观\u写入
      锁定该数据库对象
    • 如果当前有另一个用户,则
      悲观写入
      锁定请求失败
      保持
      悲观的写入
      锁定或
      悲观的读取
      锁定 那个数据库对象
    设置查询提示(作用域) 查询提示可以在以下范围内设置(从全局到本地):

    对于整个持久性单元-使用
    persistence.xml
    属性:

    <properties>
       <property name="javax.persistence.query.timeout" value="3000"/>
    </properties>
    
    对于EntityManager-使用
    createEntityManager
    方法:

    Map<String,Object> properties = new HashMap();
    properties.put("javax.persistence.query.timeout", 4000);
    EntityManagerFactory emf =
      Persistence.createEntityManagerFactory("pu", properties);
    
    Map<String,Object> properties = new HashMap();
    properties.put("javax.persistence.query.timeout", 5000);
    EntityManager em = emf.createEntityManager(properties);
    
    对于
    命名查询
    定义-使用
    提示
    元素:

    @NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
        hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
    
    对于特定的查询执行-使用
    setHint
    方法(在查询执行之前):

    资源链接:
  • 您可以在Spring数据中使用:

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")})
    Stock findById(String id)
    

    对于SpringData1.6或更高版本,我们可以使用SpringDataJPA提供的@Lock注释

    此外,还可以使用@QueryHints设置锁定超时。最初,默认CRUD方法中不支持查询提示注释,但它在fix 1.6M1之后可用。

    下面是一个悲观锁的示例,悲观锁的写入模式类型为独占锁

    @Lock(LockModeType.PESSIMISTIC_WRITE) 
    @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value   ="5000")}) 
    Customer findByCustomerId(Long customerId);
    

    javax.persistence.lock.timeout在如下所示的情况下似乎对我也不起作用:

    @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})
    
    但后来我尝试了其他有效的方法。现在我不再使用@Repository和crudepository,而是使用实体管理器配置我的hbernate。使用createQuery以及锁定和设置锁定超时。此配置正在按预期工作。 我有两个事务在并行中运行,并试图在DB中锁定完全相同的行。第一个事务能够获取写锁并在释放锁之前保持锁大约10秒。同时,第二个事务尝试获取同一行上的锁,但由于javax.persistence.lock.timeout设置为15秒,所以它等待释放锁,然后获取自己的锁。因此使流序列化

    @Component
    public class Repository {
    
        @PersistenceContext
        private EntityManager em;
    
        public Optional<Cache> getById(int id){
            List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
                                .setParameter(1, id)
                                .setHint("javax.persistence.lock.timeout", 15000)
                                .setLockMode(LockModeType.PESSIMISTIC_WRITE)
                                .getResultList();
    
        
            return Optional.ofNullable(list.get(0));
        }
        
        public void save(Cache cache) {
            cache = em.find(Cache.class, cache.getId());
            em.merge(cache);
        }
    }
    
    @组件
    公共类存储库{
    @持久上下文
    私人实体管理者;
    公共可选getById(int-id){
    List List=em.createQuery(“从缓存c中选择c,其中c.id=?1”)
    .setParameter(1,id)
    .setHint(“javax.persistence.lock.timeout”,15000)
    .setLockMode(LockModeType.悲观写入)
    .getResultList();
    返回可选的.ofNullable(list.get(0));
    }
    公共无效保存(缓存){
    cache=em.find(cache.class,cache.getId());
    合并(
    
    @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})
    
    @Component
    public class Repository {
    
        @PersistenceContext
        private EntityManager em;
    
        public Optional<Cache> getById(int id){
            List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
                                .setParameter(1, id)
                                .setHint("javax.persistence.lock.timeout", 15000)
                                .setLockMode(LockModeType.PESSIMISTIC_WRITE)
                                .getResultList();
    
        
            return Optional.ofNullable(list.get(0));
        }
        
        public void save(Cache cache) {
            cache = em.find(Cache.class, cache.getId());
            em.merge(cache);
        }
    }