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

Spring Hibernate多租户中鉴别器模型的事务支持

仲承福
2023-03-14

我们目前的开发基于多租户中的鉴别器模型。以下是我们目前正在使用的技术堆栈,

  • Spring3.1.1。释放
  • Hibernate4.1.6。最终版本

我们通过在每个表中分别保留一列来维护租户id。创建会话时租户id筛选器。

示例模型类。

@Entity
@FilterDef(name = "tenantFilter", parameters = @ParamDef(name = "tenantIdParam", type = "string"))
@Filters(@Filter(name = "tenantFilter", condition = "tenant_id = :tenantIdParam"))
@Table(name = "assessment")
public class Assessment implements java.io.Serializable, Comparable<Assessment> {

    private static final long serialVersionUID = -2231966582754667029L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Long id;
    @Column(name = "tenant_id", nullable = false, updatable = false)
    private String tenantId;

        // rest of the code...
}

这是会话工厂的配置

<!-- create database connection pool -->
    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driverClassName}" />
        <property name="jdbcUrl" value="jdbc:mysql://${jdbc.host}:3306/${jdbc.database}?createDatabaseIfNotExist=true&amp;autoReconnect=true&amp;useUnicode=true&amp;connectionCollation=utf8_general_ci&amp;characterEncoding=UTF-8" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="idleConnectionTestPeriodInMinutes" value="60"/>
        <property name="idleMaxAgeInMinutes" value="240"/>
        <property name="maxConnectionsPerPartition" value="30"/>
        <property name="minConnectionsPerPartition" value="10"/>
        <property name="partitionCount" value="3"/>
        <property name="acquireIncrement" value="5"/>
        <property name="statementsCacheSize" value="100"/>
        <property name="releaseHelperThreads" value="3"/>
    </bean>

    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="lk.gov.elg.orm.model"/>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
                hibernate.hbm2ddl.auto=update
            </value>
        </property>
    </bean>

    <bean id="tenantBasedSessionFactory" class="lk.gov.elg.orm.dao.impl.TenantBasedSessionFactoryImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

租户基础会话工厂

public class TenantBasedSessionFactoryImpl implements TenantBasedSessionFactory {

    private SessionFactory sessionFactory;

    @Override
    public Session getTenantBasedSession(Object tenantId) {
        Session session = sessionFactory.openSession();
        session.enableFilter("tenantFilter").setParameter("tenantIdParam", tenantId);
        return session;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session getAllTenantBasedSession() {
        Session session = sessionFactory.openSession();
        return session;
    }
}

示例服务类

@Service("assessmentService")
public class AssessmentServiceImpl implements AssessmentService {

    @Autowired
    private AssessmentDao assessmentDao;

    public Long saveAssessment(Assessment assessment, Object tenantId) {
        return assessmentDao.saveAssessment(assessment, tenantId);
    }
}

示例DAO类

@Repository("assessmentDao")
public class AssessmentDaoImpl implements AssessmentDao {

@Autowired
private TenantBasedSessionFactory tenantBasedSessionFactory;

public Long saveAssessment(Assessment assessment, Object tenantId) {
        Session session = tenantBasedSessionFactory.getTenantBasedSession(tenantId);
        try {
            session.beginTransaction();
            session.save(assessment);
            session.getTransaction().commit();
            return assessment.getId();
        } catch (HibernateException e) {
            logger.error("Error in persist assessment:", e);
            session.getTransaction().rollback();
            return null;
        } finally {
            session.close();
        }
    }
}

我想知道有没有一种方法可以通过这个数据库事务鉴别器模型获得spring事务支持?另一件事是,我想知道将事务处理交给spring而不是由我们自己来处理是否有任何好处?

提前谢谢。

共有1个答案

饶骁
2023-03-14

我也有类似的问题,我使用aspect而不是定制sessionfactory来解决它,所以我可以利用注释驱动的事务支持

下面的代码是用于注释@Tennant的方面

@Aspect
public class TennantAspect {

    @Autowired
    private SessionFactory sessionFactory;


    @Around("@annotation(Tennant)")
    public Object enableClientFilter(ProceedingJoinPoint pjp) throws Throwable {
        Object obj;
        boolean isDAO=(pjp.getTarget() instanceof BaseDAO<?,?>);
        try {
            if(isDAO){
                Authentication auth=SecurityContextHolder.getContext().getAuthentication();
                if(auth!=null){
                    User user=(User) auth.getPrincipal();
                    this.sessionFactory.getCurrentSession().enableFilter("clientFilter").setParameter("clientId", user.getClientId());
                }
            }
            obj=pjp.proceed();
        }finally {
            if(isDAO)
                this.sessionFactory.getCurrentSession().disableFilter("clientFilter");
        }
        return obj;
    }
}

希望这能解决你的问题。

或者,您也可以通过Hibernate查看租赁支持

http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.htmlhttps://github.com/mariofts/spring-multitenancy

 类似资料:
  • null 如何实现:Spring Data JPA不支持全局筛选器,所以我需要添加定制Spring Data JPA存储库,该存储库可以反过来为基于鉴别器的解决方案应用全局筛选器? 到底有没有可能用Spring Data JPA+Hibernate 3实现我的需求?

  • 我已经在web上阅读了几篇关于多租户(针对SaaS应用程序中的不同客户端)的文章(即这个和那个)。一旦您决定采用基于鉴别器的方法,hibernate文档声明,版本4不支持这种方法,但将在版本5中提供。 尽管如此,您可能会找到几篇关于为此目的使用hibernate过滤器的文章(即这篇和那篇)。 我想知道,如果基于过滤器的解决方案可以的话,为什么在版本5中会有一些特殊的实现呢。因此:基于过滤器的解决方

  • 我有一个JPA应用程序正在运行,现在我想支持多租户。我喜欢使用XML而不是注释。 我有两个orm。从持久性引用的xml。xml。 我喜欢对所有实体使用相同的多租户配置:单个表,鉴别器列是tenantUserId,上下文属性是tenant。用户ID。 根据:https://wiki.eclipse.org/EclipseLink/Examples/JPA/EclipseLink-ORM.XML 是否

  • 我有一个应用程序,它使用spring 4 . 0 . 1 JPA hiba Nate 4 . 2 . 8(spring的JpaTransactionManager,localcontainereentitymanagerfactorybean,带有HibernateJpaDialect和apache的BasicDataSource作为数据源)进行数据库访问。在某个时刻,应用程序开始一个长时间运行的

  • 我正在构建一个应用程序,它应该服务于多个租户,并存储他们非常敏感的数据。每个租户都有多个用户。我的后端堆栈是用spring boot Hibernate5构建的。我希望hibernate处理多租户问题,所以我有两个问题要问专家: 如果我使用的是每租户模式范式,如何在登录时将用户名与租户关联?每个租户都有自己的用户表,那么我如何知道用户名属于哪个租户呢? 在注册时,什么是正确的方法来动态创建新模式?

  • 问题内容: 是否可以强制休眠将歧视符列用于继承的继承类型?根据JPA2.0规范,这应该可行,但是我无法在休眠状态下实现。 例: 使用hibernate.hbm2ddl.auto create时,这甚至都不会在表PARENT中创建列TYPE。 我知道InheritanceType.JOINED可以在不定义鉴别符列的情况下工作,但是它是非常无效的,因为在使用鉴别符列中的信息时,休眠需要在父对象和所有子