2

我正在使用 Oracle Spatial,并且我有一个带有 SDO_GEOMETRY 字段的表。该表映射到 JPA 实体。我想让 SDO_GEOMETRY 字段映射到 javaoracle.spatial.geometry.JGeometry类型。

我想我应该使用 JPA转换器并在java.sql.Struct(或可能oracle.sql.STRUCT)之间进行转换。

问题是转换为 Struct 的 JGeometry 方法JGeometry.storeJS(Connection conn, JGeometry geom)需要 jdbc 连接作为参数。

springEntityManagerFactory配置了持久化单元名称,持久化单元包含数据源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

If you use spring, and you need to use both JPA and JDBC, you should :

  • construct a datasource bean and make connection pooling there (or get if from jndi(*))
  • inject that datasource in one on the spring helpers for building the EntityManagerFactory (such as LocalContainerEntityManagerFactoryBean)
  • inject that datasource in any bean where you want to do direct JDBC

That way you can use JPA for your normal DAO, and still have access to JDBC in special parts - without a too strong dependance of the internals of your JPA provider.

EDIT:

(*) If your datasource is defined by a jndi name, all is fine. Expose it as a bean (ref)

If using Spring's XML schema based configuration, setup in the Spring context like this:

<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" />

Alternatively, setup using simple bean configuration like this:

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

As you are using a JpaTransactionManager, there will not be any problem because as specified in spring javadoc This transaction manager also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access JPA and services which use plain JDBC (without being aware of JPA)! provided you get your Connection through DataSourceUtils.getConnection(javax.sql.DataSource)

EDIT2 :

Ok now the only problem is how to access a singleton bean from a non bean object. A simple way to solve it is to create a holder singleton bean with a static method.

@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;
    }
}

Then in any object, be it a bean or not, you can use

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

那会很棘手。纯粹来自 jpa api。您将不得不深入研究特定的提供者实现并获取DataSource对象或PersistenceUnitInfo对象。

从这里你可以得到Connection对象。

现在取决于您正在工作的环境。如果您在 JavaEE 环境中,并且注入 EntityManager 或其 EntityManagerFactory,则无法保证返回实例是提供者自己实现的实例,因为这可能只是实现接口的代理,因此与提供者自己的实现。

在 JSE 环境中,由于您是创建EntityManagerFactoryfrom的人Persistence.createEntityManagerFactory(),您可以调整提供程序以获取连接。

于 2014-07-09T12:55:14.477 回答