java - 如何访问 JPA 转换器中的 jdbc 连接?

标签 java jpa jdbc oracle-spatial

我正在使用 Oracle Spatial,并且有一个包含 SDO_GEOMETRY 字段的表。 该表映射到 JPA 实体。我希望将 SDO_GEOMETRY 字段映射到 java oracle.spatial.geometry.JGeometry 类型。

我想我应该使用 JPA Converter以及与java.sql.Struct(或者oracle.sql.STRUCT)之间的转换。

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

spring EntityManagerFactory配置了持久化单元名称,持久化单元包含数据源jndi名称,数据源定义在tomcat中,作为连接池。

知道如何在转换器中获取连接吗?

这就是我想要实现的目标:

@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。

更新了更多信息:

Spring 配置:

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

最佳答案

如果您使用 spring,并且需要同时使用 JPA 和 JDBC,您应该:

  • 构造一个数据源 bean 并在那里建立连接池(或从 jndi(*) 获取 if)
  • 将该数据源注入(inject)到 Spring 助手中,以构建 EntityManagerFactory (如LocalContainerEntityManagerFactoryBean)
  • 将该数据源注入(inject)到您想要执行直接 JDBC 的任何 bean 中

这样,您就可以将 JPA 用于您的普通 DAO,并且仍然可以在特殊部分访问 JDBC - 而不会对 JPA 提供程序的内部结构有太强的依赖性。

编辑:

(*) 如果您的数据源是由 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 中所指定的此事务管理器还支持事务内的直接数据源访问(即使用相同数据源的纯 JDBC 代码)。这允许混合访问 JPA 的服务和使用普通 JDBC 的服务(不知道 JPA)!只要您获得 Connection通过DataSourceUtils.getConnection(javax.sql.DataSource)

编辑2:

现在唯一的问题是如何从非 bean 对象访问单例 bean。解决这个问题的一个简单方法是使用静态方法创建一个 holder 单例 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);

关于java - 如何访问 JPA 转换器中的 jdbc 连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24649867/

相关文章:

java - 如何使用 Spring webflux 将实时进度发送到 webclient?

java - 在引用管理表 hibernate 的用户表上插入值 1

java - 在测试之间重置 JPA 生成的值

Java程序在执行批处理时抛出异常

java - 如何使用 JDBC 从两个不同的 MySQL 数据库检索数据?

java - 为什么 Java 允许将原始 List 传递给通用 List 构造函数?

java - 如何动态调用Java中的方法

java - 使用 @JsonSubTypes 进行反序列化以获得无值 - 缺少属性错误

java - Map<String, List> 或 List<List> 的 Hibernate 注释

java - 如何使用 JDBC 和连接池实现 DAO 管理器?