如何为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)
- 用户名
- 地址等
<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;
}