gpt4 book ai didi

hibernate - 如何为 sessionFactory.getCurrentSession() 启用 hibernate 过滤器?

转载 作者:行者123 更新时间:2023-12-02 22:06:35 25 4
gpt4 key购买 nike

假设有一个用户表,其结构为:

用户

  • 列出项目
  • 用户 ID (PK)
  • 公司(PK)
  • 用户名
  • 地址...等

我只想检索当前公司的用户(用户可以通过UI更改公司,因此公司是一个运行时参数)

同样,还有许多其他表具有与公共(public)列(公司)类似的结构,并且我想将数据限制为仅当前公司,因此我使用 hibernate 过滤器来过滤数据。

Hibernate 注释:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">Dialect....</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>User</value>
.....
</list>
</property>
</bean>

过滤器定义:

@org.hibernate.annotations.FilterDef(name="restrictToCurrentCompany",    parameters = {@org.hibernate.annotations.ParamDef(            name = "currentCompanyNumber", type = "int"        )    })@Entity@Table(name = "USER")@org.hibernate.annotations.Filter(        name = "restrictToCurrentCompany",        condition="company = :currentCompanyNumber")public class User implements Serializable {    private int company;    private String userName;    ...etc..}

Dao's:

@Repository@Transactional(readOnly = true)public class UserDAOImpl implements UserDAO {    @Autowired(required = true)    private SessionFactory sessionFactory;    public Set getUsers(){        .....Criteria queries to retrieve users for the current company         }    private Session getSession(){        return sessionFactory.getCurrentSession();    }}

If I change the getSession like so;

private Session getSession(){
Session session = sessionFactory.getCurrentSession();
Filter filter = session.enableFilter("restrictToCurrentCompany");
filter.setParameter("currentCompanyNumber", UserUtils.getCurrentCompany());
return sessionFactory.getCurrentSession();
}

然后我可以启用过滤器,一切看起来都不错,但是不是在获取 session 期间启用过滤器,是否有更简单的替代方案来为整个 session 工厂/应用程序级别应用和启用过滤器?如果是这样,我该如何使用 spring 配置来做到这一点?

我尝试 Hook hibernate 拦截器(预加载事件监听器),但我有点不确定这是否是正确的方法,或者我应该使用上面列出的 getSession 方法来启用过滤器?

最佳答案

您拥有的解决方案非常简单,但我猜您正在尝试实现它,这样您就不必在每个 DAO 中提供“getSession”实现。最终,您实现此目的的方法将取决于您希望使用此过滤器的灵 active 。这里有两种方法可以解决这个问题。

最简单的方法是简单地让您的 UserDAOImpl 扩展一个新的基类,其中包含“getSession”逻辑。此方法将允许您减少代码,因为您将在大多数情况下应用此过滤器逻辑,但随后您可以在需要时覆盖过滤。

你可以创建这样的东西:

public class BaseDAO
{

// ... possibly some other methods and variables

@Autowired(required = true)
private SessionFactory sessionFactory;

protected Session getSession()
{
//Your session filter logic above
}
}

现在您可以将 UserDAOImpl 子类化,并在需要执行某些操作时获取 session 。这是一种非常简单的方法来完成您正在寻找的事情,但它并不是万无一失的。如果您正在编写一个供其他人使用的框架,那么什么会阻止他们通过 Spring 注入(inject)来简单地获取对您的 SessionFactory 的引用,然后他们可以获得未经过滤的 Session?在某些情况下,您可能希望对可以对所有数据起作用的管理流程进行此操作,但我将描述的下一种方法应该可以防止这种情况发生。

解决问题的第二种方法涉及使用 AOP 将 SessionFactory 的 getSession 方法与您的逻辑包装在一起,以便在返回 session 之前应用过滤器。此方法意味着即使有人自己获得了对您的 SessionFactory 的引用,他们仍然会应用此过滤逻辑。

首先,如果您不熟悉 Spring 中的 AOP,请查看引用文献 http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html 。我将使用基于模式的方法将建议应用于 Hibernate,因为我们不想修改 Hibernate 的源代码。 ;) 您可以在 http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-schema 找到此方法的详细信息。 .

首先,确保 Spring 的应用程序上下文 XML 中有以下架构和 aop:config 部分:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
...
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

...

<aop:config>
<aop:aspect id="forceFilter" ref="sessionFilterAdvice">
<aop:pointcut id="hibernateSessionFactoryGetSession"
expression="execution(* org.hibernate.SessionFactory.openSession(..))" />
<aop:after-returning method="setupFilter"
pointcut-ref="hibernateSessionFactoryGetSession" returning="session" />
</aop:aspect>
</aop:config>

...
</beans>

接下来,您需要向项目添加一个 bean,以实现我们上面使用 aop:aspect 标记引用的 sessionFilterAdvice bean。创建以下类:

package net.grogscave.example;

import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

@Service
public class SessionFilterAdvice
{
public void setupFilter(Session session)
{
Session session = sessionFactory.getCurrentSession();
Filter filter = session.enableFilter("restrictToCurrentCompany");
filter.setParameter("currentCompanyNumber", UserUtils.getCurrentCompany());
}
}

最后要确保的是您的项目包含 spring-aop jar 和aspectjweaver jar。我不知道您是否使用依赖项管理,但您需要以某种方式将这些 jar 放入您的项目类路径中。

您现在应该能够重新编译您的项目,并且现在对实现 SessionFactory 的类上的任何 openSession 方法的任何调用都会将您的过滤器添加到其中。

关于hibernate - 如何为 sessionFactory.getCurrentSession() 启用 hibernate 过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5680750/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com