我使用的是Oracle Spatial,我有一个带有SDO_GEOMETRY字段的表。
该表映射到JPA实体。我想将SDO_GEOMETRY字段映射到java oracle.spatial.geometry.JGeometry
类型。
我想我应该使用JPA Converter并转换为java.sql.Struct
(或者oracle.sql.STRUCT
)。
问题是转换为Struct的JGeometry方法JGeometry.storeJS(Connection conn, JGeometry geom)希望将jdbc连接作为参数。
spring 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。
更新了更多信息:
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();
}
}
答案 0 :(得分:2)
如果使用spring,并且需要同时使用JPA和JDBC,则应该:
EntityManagerFactory
(例如LocalContainerEntityManagerFactoryBean
)通过这种方式,您可以将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 中指定此事务管理器还支持在事务中直接访问DataSource(即使用相同DataSource的纯JDBC代码)。这允许混合访问JPA的服务和使用普通JDBC的服务(不知道JPA)!如果你得到Connection
到DataSourceUtils.getConnection(javax.sql.DataSource)
EDIT2:
好的,现在唯一的问题是如何从非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);
答案 1 :(得分:0)
那会很棘手。纯粹来自jpa api。您将不得不深入了解特定的提供程序实现并获取DataSource
对象或PersistenceUnitInfo
对象。
从这里你可以抓住Connection
对象。
现在取决于您正在使用的环境。如果您在JavaEE环境中,并且注入EntityManager或其EntityManagerFactory,则无法保证返回实例是提供者自己的实现的实例,因为这可能只是实现接口的代理,因此与提供商自己的实施。
在JSE环境中,由于您是从EntityManagerFactory
创建Persistence.createEntityManagerFactory()
的人,因此您可以调整提供程序以获取连接。