Решение, которое у вас есть, довольно простое, но я предполагаю, что вы пытаетесь сделать так, чтобы вам не приходилось предоставлять реализацию 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 и получить сеанс, когда ему нужно что-то сделать. Это очень простой способ сделать то, что вы ищете, но он не является надежным. Если вы пишете фреймворк для использования другими, то что может помешать им просто получить собственную ссылку на ваш SessionFactory, если Spring вставит его, и тогда они смогут получить нефильтрованный сеанс? Это может потребоваться при определенных обстоятельствах для административных процессов, которые могут воздействовать на все данные, но следующий способ, который я опишу, должен предотвратить это.
Этот второй способ решения проблемы заключается в использовании AOP, чтобы обернуть метод getSession SessionFactory в логику, чтобы применить фильтр перед возвратом сеанса. Этот метод означает, что даже если кто-то получит ссылку на вашу SessionFactory, он все равно будет применять эту логику фильтрации.
Во-первых, если вы не знакомы с 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.
Сначала убедитесь, что у вас есть следующая схема и раздел aop: config в контексте XML вашего приложения для весны:
<?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-компонент в ваш проект для реализации bean-компонента sessionFilterAdvice, на который мы ссылаемся выше с помощью тега aop: aspect. Создайте следующий класс:
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());
}
}
Последнее, на что нужно обратить внимание, - это то, что ваш проект включает в себя банку с пружинной крышкой и банку aspectjweaver. Я не знаю, используете ли вы управление зависимостями или нет, но вам как-то нужно вставить эти файлы в путь к классам вашего проекта.
Теперь вы сможете перекомпилировать свой проект, и теперь любые вызовы любого из методов openSession в классах, которые реализуют SessionFactory, добавят к ним ваш фильтр.