2

Oracle Spatial を使用しており、SDO_GEOMETRY フィールドを持つテーブルがあります。テーブルは JPA エンティティにマップされます。oracle.spatial.geometry.JGeometrySDO_GEOMETRY フィールドを Javaタイプにマップしたいと考えています。

JPAコンバーターjava.sql.Structを使用して、 (または)との間で変換する必要があると考えましたoracle.sql.STRUCT

問題は、構造体に変換する JGeometry メソッドであるJGeometry.storeJS(Connection conn, JGeometry geom)が、パラメーターとして jdbc 接続を必要とすることです。

スプリングEntityManagerFactoryは永続ユニット名で構成され、永続ユニットにはデータ ソースの jndi 名が含まれ、データ ソースは tomcat で接続プールとして定義されます。

Connectionコンバーターでを取得する方法について何か考えはありますか?

これは私が達成したいことです:

@Converter(autoApply = true)
public class GeometryConverter implements AttributeConverter<JGeometry, Struct> {

  @Override
  public Struct convertToDatabaseColumn(JGeometry geometry) {
    // How to get this connection ?
    return JGeometry.storeJS(connection, geometry);
  }

  @Override
  public JGeometry convertToEntityAttribute(Struct struct) {
    try {
      return JGeometry.loadJS(struct);
    } catch (SQLException e) {
      throw new RuntimeException("Failed to convert geometry", e);
    }
  }
}

Spring 4、spring-data-jpa 1.6、Hibernate 4、Tomcat 8、Oracle 12c を使用しています。

詳細情報で更新

春の構成:

@Configuration
@EnableJpaRepositories("com.package.repository")
@EnableTransactionManagement
@ComponentScan("com.package")
public class SpringConfig {

  @Bean(name = "entityManagerFactory", destroyMethod = "destroy")
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setPersistenceUnitName("persistence-unit");
    return emf;
  }

  @Bean(name = "transactionManager")
  public JpaTransactionManager getTransactionManager() {
    return new JpaTransactionManager();
  }
}
4

2 に答える 2

2

Spring を使用していて、JPA と JDBC の両方を使用する必要がある場合は、次のことを行う必要があります。

  • データソース Bean を構築し、そこで接続プールを作成します (または、jndi(*) から取得した場合)
  • EntityManagerFactory(などLocalContainerEntityManagerFactoryBean)を構築するためのSpringヘルパーの1つにそのデータソースを注入します
  • 直接JDBCを実行したい任意のBeanにそのデータソースを注入します

そうすれば、JPA プロバイダーの内部に過度に依存することなく、通常のDAO にJPA を使用しながら、特別な部分で JDBC にアクセスできます。

編集:

(*) データソースが jndi 名で定義されている場合、すべて問題ありません。Bean として公開する ( ref )

Spring の XML スキーマ ベースの構成を使用している場合は、Spring コンテキストで次のようにセットアップします。

<xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee 
                    http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">
...
<jee:jndi-lookup id="dbDataSource"
   jndi-name="jdbc/DatabaseName"
   expected-type="javax.sql.DataSource" />

または、次のような単純な Bean 構成を使用してセットアップします。

<bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/>
</bean>

JpaTransactionManager を使用しているため、Spring javadoc で指定されているように、このトランザクション マネージャーはトランザクション内の直接 DataSource アクセスもサポートしているため、問題はありません(つまり、同じ DataSource で動作するプレーンな JDBC コード)。これにより、JPA にアクセスするサービスとプレーンな JDBC を使用するサービスを (JPA を意識せずに) 混在させることができます。あなたがあなたConnectionを通り抜ければDataSourceUtils.getConnection(javax.sql.DataSource)

EDIT2:

さて、唯一の問題は、非 Bean オブジェクトからシングルトン Bean にアクセスする方法です。これを解決する簡単な方法は、静的メソッドを使用してホルダーシングルトン Bean を作成することです。

@Bean
public class DataSourceHolder implements InitializingBean {
    private DataSource dataSource;

    private static DataSourceHolder instance;

    public static DataSource getDataSource() {
        return instance.dataSource;
    }

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        DataSourceHolder.instance = this;
    }
}

次に、Bean であるかどうかに関係なく、任意のオブジェクトで使用できます

DataSource ds = DataSourceHolder.getDataSource();
Connection con = DataSourceUtils.getConnection(ds);
于 2014-07-10T06:12:38.940 に答える