题
有没有人尝试使用Jooq与弹簧框架一起使用,还是我打破了新的地面?
其他提示
我试图将JOOQ用作建设者库来为Spring的JDBCtemplate和相关类提供查询。不幸的是,JOOQ似乎将两个概念组合到同一集类别:SQL生成和查询执行。就我而言,我想要前者,但想让春天处理后者。不过,它确实有效。例如,您可以执行这样的操作(使用JOOQ 2.X API):
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);
您需要做的/知道以使Jooq与Spring一起工作:
- 得到
java.sql.Connection
通过事务管理器绑定到线程。 - 通过异常翻译正确处理交易
- 了解Jooq 工厂 对象(尽管名称)不是线程安全。因此,将需要每次使用实例化新对象(不要做其他情况 回答).
因此,对于第一个和第二种情况,我提供了这种要旨: https://gist.github.com/3669307 做什么 卢卡斯推荐.
对于第三种情况,您可以基本创建工厂的工厂(其中包含 DataSource
)或只是实例化新的 Factory
使用有线的每个方法中的对象 DataSource
在您的春季组件中。
@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
}
}
至于设置侦听器,您可以使用JOOQ的配置支持,以避免程序化创建。
我不会介绍你如何设置 DataSource
在春季,由于无数/更好的地方涵盖了这种情况。
与JOOQ一起运行春季交易要简单得多(除非我忘记了一些东西):
只需将您的数据源包装到
org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
可选的: :延迟打开JDBC连接,直到第一个实际的SQL语句发生使用
org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
因此,作为一个样本,以“交易”和“懒惰”的形式创建JOOQ工厂
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!
希望这对某人有帮助。
春季应用程序上下文配置。
<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>
它将用给定的连接自动填充公共工厂(是的,它可以是一个合并的连接,具有自动关闭等。现在,公共事件。注意:无需修改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);
}
}
最后,只需致电工厂即可。
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);
}
完毕!
假设您正在使用Spring来构建WebApp,则您可能想做这样的事情:
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
}
您可能希望通过春季的依赖注入来获取数据源,因为您的Web容器,Tomcat或WhathaveYou正在提供数据源并进行连接池。在您的春季配置文件之一中,您会拥有类似的东西
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
上面代码在(或某些为数据源提供该代码的对象)中的对象可以在弹簧文件中具有配置,以便使用数据源实例化,例如
<bean id="fooService" class="com.fubar.FooServiceImpl">
<constructor-arg ref="dataSource" type="javax.sql.DataSource" />
</bean>
字符串“ JDBC/DataSource”的部分将对应于Web容器中配置的资源名称。这有所不同,但是对于Tomcat来说,它可能是conf/cattalina/catalina/localhost的上下文文件,例如
<?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>
对于Java配置(默认为Spring Boot),您可以使用以下代码:
/* 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());
}
最简单的方法(我发现)与JOOQ一起使用春季交易,在这里给出: http://blog.liftoffllc.in/2014/06/jooq-and-transactions.html
看看这个答案以更好地解释: https://stackoverflow.com/a/24380508/542108