当前位置: 首页 > 知识库问答 >
问题:

多租户配置:事务上的StaleObjectStateException(hibernate spring数据jpa)

高飞翮
2023-03-14

我试图设置一个配置来管理一个多租户环境,使用sping-start、sping-data-jpa、hibernate和mysql(相同的模式,每个租户表都有一个tenant_code列)。对于依赖项,父maven项目是sping-boo-starter-父(2.1.2.发布)。

在保存实体hibernate抛出此异常:org.hibernate.StaleObjectStateExcture:行被另一个事务更新或删除(或未保存的值映射不正确):

重点步骤包括:

  1. 使用自定义Spring HandlerInterceptorAdapter截取租户代码(我读取oAuth2令牌并提取自定义属性租户代码);
  2. 将租户代码保存在@quiestScope bean中;

    在保存
  3. 定义一个自定义的Hibernate空截取器来截取保存操作,并在之前设置租户代码(在@请求范围bean上拍摄)

    在阅读
  4. 在抽象实体(由我的所有实体扩展)中,我定义@Filter并通过AOP设置它

如果在拦截器中我重写onSave方法,则会出现以下异常:

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.test.module.api.domain.entity.User#22]
    at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2522) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3355) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3229) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3630) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1454) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3283) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2479) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:532) ~[spring-orm-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at com.test.module.api.service.UserServiceImpl$$EnhancerBySpringCGLIB$$baf4f87e.updateUser(<generated>) ~[classes/:na]
    at com.test.module.api.web.UserController.updateUser(UserController.java:38) ~[classes/:na]


这里的代码是:
来自请求头的Spring拦截器:

    @Component
    public class TokenInterceptor extends HandlerInterceptorAdapter {
        public final String TENANT_CODE = "tenant_code";

        @Autowired
        private CurrentUser currentUser;

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            String tenantCode = ... extract tenant code from request...;
            currentUser.setTenantCode(tenantCode);        
            return true;
        }
    }


在hibernate中设置inteceptor的类:

    @Component
    public class TenantHibernateInterceptorCustomizer implements HibernatePropertiesCustomizer {

        @Autowired
        private TenantJpaInterceptor jpaInterceptor;

        @Override
        public void customize(Map<String, Object> hibernateProperties) {
            hibernateProperties.put("hibernate.session_factory.interceptor", jpaInterceptor);
        }

    }


Hibernate自定义侦听器:

    @Component
    public class TenantJpaInterceptor extends EmptyInterceptor {
        //Comment to test if problem is about spring context
        //@Autowired
        //private CurrentUser currentUser;

        @Override
        public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
            if (entity instanceof TenantAuditable) {
                //((TenantAuditable<?>) entity).setTenandCode(currentUser.getTenantCode());
                //if i comment this line everythings works (without tenant code)
                ((TenantAuditable<?>) entity).setTenandCode("TEST");            
            }
            return false;
        }
    }


服务层:

    @Transactional
    public UpsertResponse<UserDto> updateUser(UserDto userDto) {
        UpsertResponse<UserDto> validationResult = CommonValidators.validateUserDto(userDto);
        if(!validationResult.isValidated()) {
            return validationResult;

        SpUser user = userRepo.findById(userDto.getUserId()).orElse(new SpUser());
        userMapper.mapUserDtoToEntity(userDto, user);
        try {
            SpUser savedUser = userRepo.save(user);
            validationResult.setEntity(userMapper.mapUserDtoFromEntity(savedUser));
            validationResult.setValidated(true);
        }catch(Exception e) {
            e.printStackTrace();
            validationResult.setValidated(false);
            validationResult.setGlobalMessage(e.getLocalizedMessage());

        }
        return validationResult;
    }

我期望插入/更新sql查询与填充tenant_code字段。


这是完整的日志

2019-01-22 01:10:57.521  INFO 14304 --- [nio-8090-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-01-22 01:10:57.523  INFO 14304 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-01-22 01:10:57.550  INFO 14304 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 27 ms
Hibernate: 
    select
        spuser0_.user_id as user_id1_0_0_,
        spuser0_.created_by as created_2_0_0_,
        spuser0_.created_date as created_3_0_0_,
        spuser0_.last_modified_by as last_mod4_0_0_,
        spuser0_.last_modified_date as last_mod5_0_0_,
        spuser0_.tenant_code as tenant_c6_0_0_,
        spuser0_.buyer_id as buyer_id7_0_0_,
        spuser0_.email as email8_0_0_,
        spuser0_.family_name as family_n9_0_0_,
        spuser0_.given_name as given_n10_0_0_,
        spuser0_.middle_name as middle_11_0_0_,
        spuser0_.user_name as user_na12_0_0_ 
    from
        sp_user spuser0_ 
    where
        spuser0_.user_id=?
2019-01-22 01:11:10.689 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [2]
Hibernate: 
    select
        spuser0_.user_id as user_id1_0_0_,
        spuser0_.created_by as created_2_0_0_,
        spuser0_.created_date as created_3_0_0_,
        spuser0_.last_modified_by as last_mod4_0_0_,
        spuser0_.last_modified_date as last_mod5_0_0_,
        spuser0_.tenant_code as tenant_c6_0_0_,
        spuser0_.buyer_id as buyer_id7_0_0_,
        spuser0_.email as email8_0_0_,
        spuser0_.family_name as family_n9_0_0_,
        spuser0_.given_name as given_n10_0_0_,
        spuser0_.middle_name as middle_11_0_0_,
        spuser0_.user_name as user_na12_0_0_ 
    from
        sp_user spuser0_ 
    where
        spuser0_.user_id=?
2019-01-22 01:11:14.414 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [2]
Hibernate: 
    insert 
    into
        sp_user
        (created_by, created_date, last_modified_by, last_modified_date, tenant_code, buyer_id, email, family_name, given_name, middle_name, user_name) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2019-01-22 01:11:23.137 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [3bf38f12-5d17-47e4-9504-ad0705289d10]
2019-01-22 01:11:23.138 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [Tue Jan 22 01:11:14 CET 2019]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [3bf38f12-5d17-47e4-9504-ad0705289d10]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [TIMESTAMP] - [Tue Jan 22 01:11:14 CET 2019]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [VARCHAR] - [null]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [VARCHAR] - [1]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [VARCHAR] - [gabriele.muscas@gmail.comx]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [VARCHAR] - [Muscas]
2019-01-22 01:11:23.140 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [9] as [VARCHAR] - [Gabrielex]
2019-01-22 01:11:23.141 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [10] as [VARCHAR] - [Giuseppe Pippo]
2019-01-22 01:11:23.141 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [11] as [VARCHAR] - [gabriele.muscas]
Hibernate: 
    update
        sp_user 
    set
        created_by=?,
        created_date=?,
        last_modified_by=?,
        last_modified_date=?,
        tenant_code=?,
        buyer_id=?,
        email=?,
        family_name=?,
        given_name=?,
        middle_name=?,
        user_name=? 
    where
        user_id=?
2019-01-22 01:11:24.912 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [3bf38f12-5d17-47e4-9504-ad0705289d10]
2019-01-22 01:11:24.912 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [Tue Jan 22 01:11:14 CET 2019]
2019-01-22 01:11:24.913 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [3bf38f12-5d17-47e4-9504-ad0705289d10]
2019-01-22 01:11:24.913 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [TIMESTAMP] - [Tue Jan 22 01:11:24 CET 2019]
2019-01-22 01:11:24.913 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [VARCHAR] - [PIPPO]
2019-01-22 01:11:24.913 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [VARCHAR] - [1]
2019-01-22 01:11:24.914 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [VARCHAR] - [gabriele.muscas@gmail.comx]
2019-01-22 01:11:24.914 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [VARCHAR] - [Muscas]
2019-01-22 01:11:24.914 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [9] as [VARCHAR] - [Gabrielex]
2019-01-22 01:11:24.915 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [10] as [VARCHAR] - [Giuseppe Pippo]
2019-01-22 01:11:24.915 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [11] as [VARCHAR] - [gabriele.muscas]
2019-01-22 01:11:24.915 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [12] as [BIGINT] - [23]
2019-01-22 01:11:24.918 ERROR 14304 --- [nio-8090-exec-2] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.supplhi.buyer.api.domain.entity.SpUser#23]]
Hibernate: 
    select
        spuser0_.user_id as user_id1_0_0_,
        spuser0_.created_by as created_2_0_0_,
        spuser0_.created_date as created_3_0_0_,
        spuser0_.last_modified_by as last_mod4_0_0_,
        spuser0_.last_modified_date as last_mod5_0_0_,
        spuser0_.tenant_code as tenant_c6_0_0_,
        spuser0_.buyer_id as buyer_id7_0_0_,
        spuser0_.email as email8_0_0_,
        spuser0_.family_name as family_n9_0_0_,
        spuser0_.given_name as given_n10_0_0_,
        spuser0_.middle_name as middle_11_0_0_,
        spuser0_.user_name as user_na12_0_0_ 
    from
        sp_user spuser0_ 
    where
        spuser0_.user_id=?
2019-01-22 01:11:24.928 TRACE 14304 --- [nio-8090-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [23]
2019-01-22 01:11:24.940 ERROR 14304 --- [nio-8090-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [com.supplhi.buyer.api.domain.entity.SpUser] with identifier [23]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.supplhi.buyer.api.domain.entity.SpUser#23]] with root cause

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.supplhi.buyer.api.domain.entity.SpUser#23]
    at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2522) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3355) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3229) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3630) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1454) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3283) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2479) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:532) ~[spring-orm-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at com.supplhi.buyer.api.service.UserServiceImpl$$EnhancerBySpringCGLIB$$baf4f87e.updateUser(<generated>) ~[classes/:na]
    at com.supplhi.buyer.api.web.UserController.updateUser(UserController.java:38) ~[classes/:na]

帮个小忙吧,谢谢

共有1个答案

许兴文
2023-03-14

根据(3.3)文档/样本,你应该实现你的(jpa)拦截器,比如:

@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
  if (entity instanceof TenantAuditable) {
    for ( int i=0; i < propertyNames.length; i++ ) {
      if ( "tenantCode".equals( propertyNames[i] ) ) {
        state[i] = currentUser.getTenantCode();
        return true;
      }
    }          
  }
  return false;
}

我很惊讶它和“测试”一起工作...

 类似资料:
  • 我正在使用Spring2.x、Spring Data REST、Hibernate5.x、MySQL创建一个服务器REST应用程序。 我按照以下准则配置了多租户:https://dzone.com/articles/spring-boot-hibernate-multitenancy-implementation,唯一的区别是我使用了每个租户一个数据库。 我有一个来创建到DB的连接,还有一个来获取

  • 我有一个KeyClope实例,为每个域创建了两个域和一个用户。 我有我的spring boot应用程序。yml(resource server-API)用于一个特定领域,并在我的代码中修复。 它正在为Realm1工作并进行验证。 但现在我可以接收来自user2(tenant2)的请求,而令牌将无效,因为公钥(realm1)对于已签名的请求jwt令牌(realm2)无效。 允许多领域多租户和动态配置

  • 我们正在开发一个多租户应用程序。在体系结构方面,我们为业务逻辑设计了共享中间层,为数据持久性设计了每个租户一个数据库。也就是说,业务层将与每个租户的数据库服务器建立一组连接(连接池)。这意味着应用程序为每个租户维护单独的连接池。如果我们预计约有5000个租户,那么这个解决方案需要高资源利用率(每个租户的应用服务器和数据库服务器之间的连接),这会导致性能问题。 我们已经通过保持公共连接池解决了这个问

  • 我认为为每个租户创建一个Redis实例是一个很好的解决方案。 我有一个包含租户id和Redisendpoint的映射,这是专用于这个租户的。 地图数据如下所示:

  • 问题内容: 我正在尝试使用此网络研讨会中概述的单独的架构方法向Java应用程序添加多租户 我想知道如何通过spring来配置多个数据源,也许是通过使用属性文件并基于租户id从spring上下文中获取数据源。 更重要的是,尽管我希望能够配置支持此多租户功能的自定义连接提供程序实现,以供Hibernate使用,而不是默认使用的注入功能。 我怎样才能做到这一点。 问题答案: 使用。

  • 问题内容: 在Spring 3应用程序中,我试图通过Hibernate 4的本机MultiTenantConnectionProvider和CurrentTenantIdentifierResolver实现多租户。我发现在Hibernate 4.1.3 中存在此问题,但是我正在运行4.1.9并仍收到类似的异常: 以下是相关代码。在I中,我现在只写了一些简单的代码,每次都只返回一个新的连接,并且在这