如何解决如何为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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。