java - JOOQ y primavera
sql spring (8)
¿Alguien ha intentado usar JOOQ con el framework Spring o estoy abriendo nuevos caminos?
Espero que esto sea de ayuda para alguien ...
Configuración del contexto de la aplicación Spring.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
<property name="searchSystemEnvironment">
<value type="boolean">true</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url"
value="jdbc:h2://${user.home}
${file.separator}tracciabilitaCanarini${file.separator}db${file.separator}basedb"/>
<property name="username" value="sa"/>
<property name="password" value="sa"/>
</bean>
<bean id="datasourceConnection"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
lazy-init="true" depends-on="dataSource">
<property name="targetObject">
<ref bean="dataSource"/>
</property>
<property name="targetMethod">
<value>getConnection</value>
</property>
</bean>
<bean id="publicFactory" class="dbLayer.db.PublicFactory" lazy-init="true"
depends-on="datasourceConnection" >
<constructor-arg index="0" ref="datasourceConnection" />
</bean>
Automáticamente llenará la fábrica pública con la conexión dada (y sí, puede ser una conexión agrupada, con cierre automático, etc., consulte la clase DriverManagerDataSource para una configuración más detallada). Y ahora, la publicFactory. Nota: no es necesario modificar la fábrica pública original generada por jOOQ.
/**
* This class is generated by jOOQ
*/
package dbLayer.db;
/**
* This class is generated by jOOQ.
*/
@javax.annotation.Generated(value = {"http://www.jooq.org", "2.0.5"},
comments = "This class is generated by jOOQ")
public class PublicFactory extends org.jooq.util.h2.H2Factory {
private static final long serialVersionUID = -1930298411;
/**
* Create a factory with a connection
*
* @param connection The connection to use with objects created from this factory
*/
public PublicFactory(java.sql.Connection connection) {
super(connection);
}
/**
* Create a factory with a connection and some settings
*
* @param connection The connection to use with objects created from this factory
* @param settings The settings to apply to objects created from this factory
*/
public PublicFactory(java.sql.Connection connection, org.jooq.conf.Settings settings) {
super(connection, settings);
}
}
Al final, simplemente llame a la fábrica.
PublicFactory vs = (PublicFactory) SpringLoader.getBean("publicFactory");
SimpleSelectQuery<VersionRecord> sq = vs.selectQuery(dbLayer.db.tables.Version.VERSION);
VersionRecord v = null;
try {
v = sq.fetchAny();
} catch (Exception e) {
log.warn("Seems that version table does not exists!", e);
}
¡Hecho!
Estaba buscando usar jOOQ como una biblioteca de constructores para proporcionar consultas a JdbcTemplate de Spring y clases relacionadas. Desafortunadamente, jOOQ parece combinar dos conceptos en el mismo conjunto de clases: generación de SQL y ejecución de consultas. En mi caso, quiero lo primero, pero quiero que Spring se encargue de lo último. Sin embargo, sí funciona. Por ejemplo, puedes hacer algo como esto (usando la API jOOQ 2.x):
Factory create = new Factory(null, SQLDialect.ORACLE);
getJdbcTemplate().query(
create.select(create.field(ID_COL),
create.field(VALUE_COL))
.from(FOO_TABLE)
.where(create.field(ID_COL).equals("ignored"))
.getSQL(),
myRowMapper,
id);
La forma más fácil, (he encontrado) el uso de Spring Transactions con jOOQ, se proporciona aquí: http://blog.liftoffllc.in/2014/06/jooq-and-transactions.html
Eche un vistazo a esta respuesta para obtener una mejor explicación: https://.com/a/24380508/542108
Para la configuración de Java (que es la predeterminada para Spring Boot) puede usar el siguiente código:
/* JOOQ Configuration */
@Bean
public DataSourceConnectionProvider dataSourceConnectionProvider() {
return new DataSourceConnectionProvider(dataSource());
}
@Bean
public DefaultConfiguration defaultConfiguration() {
DefaultConfiguration defaultConfiguration = new DefaultConfiguration();
defaultConfiguration.setConnectionProvider(dataSourceConnectionProvider());
defaultConfiguration.setSQLDialect(SQLDialect.POSTGRES);
return defaultConfiguration;
}
@Bean
public DSLContext dslContext() {
return new DefaultDSLContext(defaultConfiguration());
}
Suponiendo que está utilizando Spring para crear una aplicación web, probablemente quiera hacer algo como esto:
try {
Connection conn = dataSource.getConnection();
try {
// Do something with JOOQ
// No need to use a JdbcTemplate!
}
finally {
if (conn != null) {
conn.close();
}
}
} catch (SQLException e) {
// your error handling
}
Probablemente desee obtener un DataSource a través de la inyección de dependencia de Spring, ya que su contenedor web, Tomcat o whewaveyou, proporciona el DataSource y realiza la agrupación de conexiones. En uno de tus archivos de configuración de primavera tendrías algo como
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
El objeto en el que se encuentra el código anterior (o algún objeto que proporcione este código con la fuente de datos) podría tener configuración en un archivo spring para crear una instancia con la fuente de datos, como
<bean id="fooService" class="com.fubar.FooServiceImpl">
<constructor-arg ref="dataSource" type="javax.sql.DataSource" />
</bean>
La parte de la cadena "jdbc / datasource" correspondería a un nombre de recurso configurado en el contenedor web. Esto varía, pero para Tomcat podría ser un archivo de contexto en conf / Catalina / localhost en la página de inicio de Tomcat, por ejemplo,
<?xml version="1.0" encoding="UTF-8"?>
<Context debug="10" reloadable="true" useNaming="true" antiJARLocking="true">
<Resource name="jdbc/datasource" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" validationQuery="SELECT 1"
username="foo" password="fubar" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost/foobase"/>
</Context>
Todo lo que necesita hacer / saber para que jOOQ funcione con spring:
- Obtenga el
java.sql.Connection
vinculado al hilo por el administrador de transacciones. - Manejar las transacciones adecuadamente a través de la traducción de excepción
- Comprenda que los objetos jOOQ Factory (a pesar del nombre) no son seguros para subprocesos. y, por lo tanto, requerirá la creación de una instancia de un nuevo objeto por uso (No hagas esta otra answer ).
Entonces, para el primer y segundo caso, ofrezco esta idea: https://gist.github.com/3669307 que hace lo que recomienda Lukas .
Para el tercer caso, puede crear básicamente una fábrica de una fábrica (que contiene la DataSource
) o simplemente crear una instancia de un nuevo objeto de Factory
en cada método utilizando la fuente de datos cableada en su componente Spring.
@Service
public class MyDaoOrService {
@Autowired
private void DataSource dataSource;
@Transactional
public void doSomeJooq(){
Settings s = new Settings();
//You could instead put this jooq configuration xml
s.getExecuteListeners().add("com.snaphop.jooq.SpringExceptionTranslationExecuteListener");
MyGeneratedFactory f = new MyGeneratedFactory(dataSource, s);
f.select(); //etc
}
}
En cuanto a la escucha de configuración, puede utilizar el soporte de configuración de JOOQ para evitar la creación programática.
No cubriré cómo configura un DataSource
en Spring, ya que está cubierto en una gran cantidad de otros / mejores lugares.
hacer que las transacciones de primavera se ejecuten con jOOQ es mucho más simple (a menos que se me olvide algo):
simplemente envuelva su fuente de datos en
org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
opcional : para retrasar la apertura de una conexión jdbc hasta que ocurra la primera instrucción sql real use
org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
así como una muestra, haga esto para crear una fábrica jOOQ con ''transacciones'' y ''pereza'' aplicadas
DataSource rawDS = /* your actual data source */
// (optional) make access lazy
final DataSource lazyDS = new LazyConnectionDataSourceProxy(rawDataSource);
// make spring transactions available in plain jdbc context
final DataSource txDS = new TransactionAwareDataSourceProxy(lazyDS);
// create jOOQ factory
Factory jooq = new Factory(txDS, /* dialect */, /* settings */)
// voila!