如何为sessionFactory.getCurrentSession()启用休眠过滤器?

| 假设有一个结构如下的User表: 用户 项目清单 userId(PK) 公司(PK) 用户名 地址...等 我只想检索当前公司的用户(用户可以通过UI更改公司,因此公司是运行时参数) 类似地,还有许多其他表具有与公用列(公司)相似的结构,并且我想将数据限制为仅当前公司,因此我正在使用休眠过滤器来过滤数据。 休眠注释:
<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 \”,     参数= {@ org.hibernate.annotations.ParamDef(             名称= \“ currentCompanyNumber \”,类型= \“ int \”         )     } ) @实体 @Table(名称= \“ USER \”) @ org.hibernate.annotations.Filter(         名称= \“ restrictToCurrentCompany \”,         条件= \“公司=:currentCompanyNumber \” ) 公共类用户实现Serializable {     私人int公司;     私有字符串userName;     ...等等.. } 道: @资料库 @Transactional(readOnly = true) 公共类UserDAOImpl实现UserDAO {     @Autowired(必填= true)     私有SessionFactory sessionFactory;     公开设置getUsers(){         .....条件查询来检索当前公司的用户     }     私人会话getSession(){         返回sessionFactory.getCurrentSession();     } } 如果我这样更改getSession;
private Session getSession(){
    Session session = sessionFactory.getCurrentSession();
    Filter filter = session.enableFilter(\"restrictToCurrentCompany\");
    filter.setParameter(\"currentCompanyNumber\", UserUtils.getCurrentCompany());
    return sessionFactory.getCurrentSession();
}
那么我可以启用筛选器,并且一切看起来都很好,但是除了在获取会话期间启用筛选器之外,还有一种更简单的替代方法可以应用,并在整个会话工厂/应用程序级别启用筛选器?如果是这样,我该如何使用spring配置呢? 我尝试连接到休眠拦截器(预加载事件侦听器),但是我不确定这是否正确,还是应该使用上面列出的getSession方法启用过滤器?     
已邀请:
您拥有的解决方案非常简单,但是我猜您正在寻找的解决方案是使它成为现实,这样您就不必在每个DAO中都提供一个“ getSession”实现。最终,实现此方法的方法将取决于您希望此过滤器具有多大的灵活性。这是我可以解决此问题的两种方法。 最简单的方法是简单地使您的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的子类,并在需要执行操作时获得会话。这是一种非常简单的方法来做您要寻找的东西,但这并不是万无一失的。如果您正在编写供其他人使用的框架,那么将阻止他们通过让Spring注入它们来简单地获取自己对SessionFactory的引用,然后他们可以获得未过滤的Session?对于在某些情况下可以对所有数据起作用的管理流程,您可能希望这样做,但是我将描述的下一种方式应避免这种情况的发生。 解决该问题的第二种方法涉及使用AOP将SessionFactory的getSession方法包装到您的逻辑中,以便在返回会话之前应用过滤器。此方法意味着,即使有人自己获得对您的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中具有以下schema和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 HBM文件: 在hbm文件中声明过滤器。这里filterByFacilityIDs是一个过滤器,而facilityIDsParam是一个List 类型参数。
<hibernate-mapping package=\"com.ABC.dvo\">
 <class name=\"ItemMasterDVO\" table=\"Item_Master\">
  ....
<set name=\"inventoryTaxesSet\" inverse=\"true\" cascade=\"all\">
<key column=\"item_ID\" />
<one-to-many class=\"InventoryTaxesDVO\" />
    <filter name=\"filterByFacilityIDs\" condition=\"Facility_ID in(:facilityIDsParam)\"/>  
</set>
</class>
<filter-def name=\"filterByFacilityIDs\">
 <filter-param name=\"facilityIDsParam\" type=\"string\"/>
</filter-def>
</hibernate-mapping>
** Java类**
public List<ItemMasterDVO> getItemMaster(String[] itemIDs, String[] facilityIDs){
    Session session = getSessionFactory().getCurrentSession();
    Criteria criteria = session.createCriteria(ItemMasterDVO.class)
        .add(Restrictions.in(\"itemNumber\", itemIDs))
        .setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
    if(facilityIDs!=null && facilityIDs.length>0){          
        org.hibernate.Filter filter = session.enableFilter(\"filterByFacilityIDs\");
        filter.setParameterList(\"facilityIDsParam\", facilityIDs);
    }   
    criteria.addOrder(Order.asc(\"itemNumber\"));
    List<ItemMasterDVO> result = criteria.list(); 
    return result;
    }
    

要回复问题请先登录注册