Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.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/5/ruby-on-rails-4/2.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
如何为sessionFactory.getCurrentSession()启用hibernate筛选器?_Hibernate_Spring_Hibernate Annotations_Hibernate Filters - Fatal编程技术网

如何为sessionFactory.getCurrentSession()启用hibernate筛选器?

如何为sessionFactory.getCurrentSession()启用hibernate筛选器?,hibernate,spring,hibernate-annotations,hibernate-filters,Hibernate,Spring,Hibernate Annotations,Hibernate Filters,假设有一个具有以下结构的用户表: 用户 列表项 用户标识(PK) 公司(PK) 用户名 地址等 我只想检索当前公司的用户(用户可以通过UI更改公司,因此公司是一个运行时参数) 类似地,还有许多其他表具有与公共列(company)类似的结构,我想将数据仅限于当前公司,因此我使用hibernate filter来过滤数据 休眠注释: <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotat

假设有一个具有以下结构的用户表:

用户

  • 列表项
  • 用户标识(PK)
  • 公司(PK)
  • 用户名
  • 地址等
我只想检索当前公司的用户(用户可以通过UI更改公司,因此公司是一个运行时参数)

类似地,还有许多其他表具有与公共列(company)类似的结构,我想将数据仅限于当前公司,因此我使用hibernate filter来过滤数据

休眠注释:

<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>
然后,我可以启用过滤器,一切看起来都很好,但是在获取会话期间,是否有更简单的替代方法来为整个会话工厂/应用程序级别应用和启用过滤器,而不是启用过滤器?如果是这样,我如何使用spring配置来实现这一点


我尝试连接到hibernate拦截器(预加载事件列表),但我有点不确定这是一种正确的方法,还是应该使用上面列出的getSession方法来启用过滤器?

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

最简单的方法是简单地让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的引用,然后获得一个未过滤的会话呢?在某些情况下,对于可以对所有数据进行操作的管理流程,您可能希望这样做,但我将介绍的下一种方法应该可以防止这种情况发生

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

首先,如果您不熟悉spring中的AOP,请查看参考资料。我将使用基于模式的方法将建议应用于Hibernate,因为我们不想修改Hibernate的源代码您可以在中找到此方法的详细信息

首先,确保spring的应用程序上下文XML中有以下模式和aop:config部分:

最后要确保的是,您的项目包括SpringAOPjar和AspectJweaverjar。我不知道您是否使用依赖关系管理,但您需要以某种方式将这些JAR放入您的项目类路径中


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

Hibernate hbm文件: 在hbm文件中声明筛选器。这里filterByFacilityId是一个过滤器,FacilityIDParam是一个列表类型参数

<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;
    }
public List getItemMaster(String[]ItemId,String[]FacilityId){
会话会话=getSessionFactory().getCurrentSession();
条件=session.createCriteria(ItemMasterDVO.class)
.add(Restrictions.in(“itemNumber”,ItemId))
.setResultTransformer(标准规范.DISTINCT\u ROOT\u实体);
如果(facilityIDs!=null&&facilityIDs.length>0){
org.hibernate.Filter Filter=session.enableFilter(“filterByFacilityId”);
filter.setParameterList(“FacilityIDParam”,FacilityId);
}   
标准.addOrder(Order.asc(“itemNumber”));
列表结果=criteria.List();
返回结果;
}

你最后做了什么,@sachink?类似地,我想以一种不太显眼的方式自动设置我的运行时过滤器值。应该可以在Spring DI容器中使用自定义请求范围的工厂注入适当的过滤
会话。但是,这个自定义工厂应该在引擎盖下使用应用程序范围的
SessionFactory
,因为创建它是一个非常昂贵的操作。
public class BaseDAO
{

    // ... possibly some other methods and variables

    @Autowired(required = true)
    private SessionFactory sessionFactory;

    protected Session getSession()
    {
        //Your session filter logic above
    }
}
<?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>
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());
    }
}
<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>
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;
    }