복붙노트

[SPRING] Spring + Hibernate SessionFactory + AbstractRoutingDataSource

SPRING

Spring + Hibernate SessionFactory + AbstractRoutingDataSource

데이터베이스 스키마간에 동적으로 전환해야하는 Spring + Hibernate / Flex 응용 프로그램이 있습니다. 이를 위해이 기사 다음에 AbstractRoutingDataSource를 구현했습니다. 불행히도 그것은 작동하지 않습니다. 실제로는 기본 스키마 (logical_public)에서 SQL을 실행합니다. 어떤 도움이라도 대단히 감사하겠습니다. 감사.

여기 내 설정 :

applicationContext.xml에는 두 개의 데이터 소스가 포함되어 있습니다. 각 데이터 소스는 다른 로그인 역할로 데이터베이스에 연결됩니다. 라우팅 데이터 소스는 String 키를 사용하여 올바른 데이터 소스를 선택합니다. SchemaConstants 클래스에는 몇개의 public static final 필드가 포함되어 있습니다.

<bean id="parentDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="org.postgresql.Driver"/>
    <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/mystore"/>
    <property name="acquireIncrement" value="3"/>
    <property name="minPoolSize" value="1"/>
    <property name="maxPoolSize" value="15"/>
    <property name="maxStatementsPerConnection" value="100"/>
    <property name="automaticTestTable" value="c3p0_test_table"/>
    <property name="numHelperThreads" value = "20"/>
</bean>

<bean id="publicDS" parent="parentDataSource">
    <property name="user" value="postgres"/>
    <property name="password" value="password"/>
</bean>

<bean id="tempSchemaDS" parent="parentDataSource">
    <property name="user" value="temp_role"/>
    <property name="password" value="tmppsw"/>
</bean>

<bean id="routingDS" class="flex.RoutingDataSource">
   <property name="targetDataSources">
      <map key-type="java.lang.String">
         <entry key="flex.SchemaConstants.LOGICAL_PUBLIC" value-ref="publicDS"/>
         <entry key="flex.SchemaConstants.TEMP_SCHEMA" value-ref="tempSchemaDS"/>
      </map>
   </property>
   <property name="defaultTargetDataSource" ref="publicDS"/>
</bean>

RoutingDataSource 구현 : 여기에 추가 할 내용이 없습니다.

public class RoutingDataSource extends AbstractRoutingDataSource
{
    @Override
    protected Object determineCurrentLookupKey()
    {
        return Globals.getSchema();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException
    {
        // TODO Auto-generated method stub
        return null;
    }
}

Globals 클래스 : 데이터 소스 키를 저장하고 조회하는 데 사용됩니다.

public class Globals
{
    private static final ThreadLocal<String> schemaHolder 
        = new ThreadLocal<String>();

    public static void setSchema(String schema)
    {
        schemaHolder.set(schema);
    }

    public static String getSchema()
    {
        return schemaHolder.get();
    }

    public static void clearCustomerType()
    {
        schemaHolder.remove();
    }
}

테스트 코드 : 각각 다른 스키마 (및 다른 테이블)에 몇 개의 레코드를 삽입하려고 시도합니다.

@RemotingInclude
@Transactional
public void test()
{
    Globals.setSchema(SchemaConstants.TEMP_SCHEMA);

    SomeDataOther someOtherData = new SomeDataOther();
    someOtherData.setName("Jorjinio");
    this.sessionFactory.getCurrentSession().save(someOtherData);


    Globals.setSchema(SchemaConstants.LOGICAL_PUBLIC);

    SomeData someData = new SomeData();
    someData.setFirstName("Hulio");
    someData.setLastName("Julio");
    this.sessionFactory.getCurrentSession().save(someData);
}

2 차 질문입니다. 이러한 상황에서 데이터 무결성을 유지하는 올바른 방법은 무엇입니까? @Transactional 특성으로 메서드에 주석을 달았지만 너무 쉽게 작동 할 것이라고 확신 할 수 없습니다. 내가 사용하고있는 transactionManager는 org.springframework.orm.hibernate3.HibernateTransactionManager 타입이다. 이 문제에 관해 아직 연구하지는 않았지만 누군가가 정보를 제공 할 수 있다면 크게 도움이 될 것입니다.

해결법

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

    1.AbstractRoutingDataSource.getConnection ()이 호출 될 때, 즉 트랜잭션 바운드 Hibernate Session이 생성 될 때 특정 데이터 소스의 선택이 실제로 발생한다는 것은 명백합니다. 귀하의 경우 @Transactional 메서드를 입력 할 때 발생합니다.

    AbstractRoutingDataSource.getConnection ()이 호출 될 때, 즉 트랜잭션 바운드 Hibernate Session이 생성 될 때 특정 데이터 소스의 선택이 실제로 발생한다는 것은 명백합니다. 귀하의 경우 @Transactional 메서드를 입력 할 때 발생합니다.

    따라서 트랜잭션 내에서 스키마를 전환 할 수 없습니다. 서로 다른 스키마에 대해 별도의 트랜잭션을 실행해야합니다. 동일한 메소드 내에서 여러 트랜잭션을 실행하려면 @Transactional 대신 프로그래밍 방식의 트랜잭션 관리 (TransactionTemplate)를 사용할 수 있습니다.

  2. from https://stackoverflow.com/questions/7378883/spring-hibernate-sessionfactory-abstractroutingdatasource by cc-by-sa and MIT license