복붙노트

[SPRING] sessionFactory.getCurrentSession ()에 대한 최대 절전 모드 필터를 설정하는 방법은 무엇입니까?

SPRING

sessionFactory.getCurrentSession ()에 대한 최대 절전 모드 필터를 설정하는 방법은 무엇입니까?

구조가있는 User 테이블이 있다고 가정 해보십시오.

사용자

그리고 현재 회사의 사용자 만 검색하려고합니다. 회사는 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",
    parameters = {@org.hibernate.annotations.ParamDef(
            name = "currentCompanyNumber", type = "int"
        )
    }
)
@Entity
@Table(name = "USER")
@org.hibernate.annotations.Filter(
        name = "restrictToCurrentCompany",
        condition="company = :currentCompanyNumber"
)
public class User implements Serializable {
    private int company;
    private String userName;
    ...etc..
}

다오의 :


@Repository
@Transactional(readOnly = true)
public class UserDAOImpl implements UserDAO {

    @Autowired(required = true)
    private SessionFactory sessionFactory;

    public Set getUsers(){
        .....Criteria queries to retrieve users for the current company     
    }

    private Session getSession(){
        return sessionFactory.getCurrentSession();
    }

}

getSession을 그렇게 변경하면;

private Session getSession(){
    Session session = sessionFactory.getCurrentSession();
    Filter filter = session.enableFilter("restrictToCurrentCompany");
    filter.setParameter("currentCompanyNumber", UserUtils.getCurrentCompany());
    return sessionFactory.getCurrentSession();
}

필터를 활성화하면 모든 것이 잘 보이지만 세션 가져 오기 중에 필터를 활성화하는 대신 전체 세션 팩토리 / 응용 프로그램 수준에 필터를 적용하고 활성화하는 간단한 방법이 있습니까? 그렇다면 스프링 구성을 사용하여 어떻게 그렇게 할 수 있습니까?

최대 절전 모드 인터셉터 (프리로드 이벤트 리스너)에 연결하려고 시도했지만이 방법이 올바른지 확실하지 않거나 위의 getSession 메서드를 사용하여 필터를 활성화해야합니까?

해결법

  1. ==============================

    1.당신이 가진 솔루션은 매우 간단하지만, 당신이하려고하는 것이 당신이 DAO 각각에서 "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이 그것을 삽입하고 필터링되지 않은 Session을 얻을 수있게함으로써 SessionFactory에 대한 참조를 얻는 것을 막을 수있는 것은 무엇입니까? 특정 상황에서 모든 데이터에 대해 작동 할 수있는 관리 프로세스가 필요할 수 있지만 다음에 설명 할 방법으로이 문제가 발생하지 않도록해야합니다.

    이 문제를 해결하는 두 번째 방법은 AOP를 사용하여 SessionFactory의 getSession 메서드를 로직으로 래핑하여 세션이 반환되기 전에 필터를 적용하는 것입니다. 이 방법은 누군가 자신의 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에서 찾을 수 있습니다.

    먼저 Spring의 애플리케이션 컨텍스트 XML에 다음 스키마와 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>
    

    다음으로 aop : aspect 태그로 위에서 언급 한 sessionFilterAdvice 빈을 구현하기 위해 빈을 프로젝트에 추가해야한다. 다음 클래스를 만듭니다.

    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가 포함되어 있다는 것입니다. 의존성 관리를 사용하는지 여부는 모르지만 프로젝트 클래스 패스에 해당 항아리를 가져와야합니다.

    이제 프로젝트를 다시 컴파일 할 수 있어야합니다. 이제 SessionFactory를 구현하는 클래스의 openSession 메소드에 대한 호출은 필터를 추가합니다.

  2. ==============================

    2.최대 절전 모드 hbm 파일 : hbm 파일에서 필터를 선언하십시오. 여기서 filterByFacilityIDs는 필터이고 facilityIDsParam은 List 유형 매개 변수입니다.

    최대 절전 모드 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>
    

    ** 자바 클래스 **

    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;
        }
    
  3. from https://stackoverflow.com/questions/5680750/how-to-enable-hibernate-filter-for-sessionfactory-getcurrentsession by cc-by-sa and MIT license