简体   繁体   English

JOOQ 和 Spring

[英]JOOQ and Spring

Has anyone tried using JOOQ with the Spring framework or am I breaking new ground?有没有人尝试过将 JOOQ 与 Spring 框架一起使用,或者我是否正在开辟新天地?

http://www.jooq.org http://www.jooq.org

Many people are using jOOQ with Spring or Spring Boot很多人都在使用 jOOQ 和 Spring 或 Spring Boot

There is also a very good tutorial by Petri Kainulainen, explaining every step to set up a project, here: Petri Kainulainen 也有一个非常好的教程,解释了设置项目的每一步,这里:

Here's a blog post about how to use jOOQ with Spring Boot, especially useful when you need the commercial distributions of jOOQ:这是一篇关于如何在 Spring Boot 中使用 jOOQ 的博客文章,当您需要 jOOQ 的商业发行版时特别有用:

I was looking to use jOOQ as an builder library for providing queries to Spring's JdbcTemplate and related classes.我希望将 jOOQ 用作构建器库,以提供对 Spring 的 JdbcTemplate 和相关类的查询。 Unfortunately, jOOQ appears to combine two concepts into the same set of classes: SQL generation and query execution.不幸的是,jOOQ 似乎将两个概念结合到同一组类中:SQL 生成和查询执行。 In my case, I want the former but want to let Spring handle the latter.就我而言,我想要前者,但想让 Spring 处理后者。 It does work, though.不过,它确实有效。 For example, you can do something like this (using jOOQ 2.x API):例如,您可以执行以下操作(使用 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);

getting spring transactions running with jOOQ is a lot simpler (unless I forgot something):使用 jOOQ 运行 spring 事务要简单得多(除非我忘记了什么):

just wrap your data source into只需将您的数据源包装到

org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy

optional : to delay opening a jdbc connection until the first actual sql statement happens use可选:延迟打开 jdbc 连接,直到第一个实际的 sql 语句发生使用

org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy

so as an sample do this to create a jOOQ factory with 'transactions' and 'lazyness' applied所以作为一个示例,这样做是为了创建一个应用了“事务”和“懒惰”的 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!

All you need to do/know to make jOOQ work with spring:为了使 jOOQ 与 spring 一起工作,您需要做/知道的所有事情:

  1. Get the java.sql.Connection bound to the thread by the transaction manager.获取事务管理器绑定到线程的java.sql.Connection
  2. Handle transactions properly through exception translation通过异常翻译正确处理事务
  3. Understand that the jOOQ Factory objects (despite the name) are not threadsafe.了解 jOOQ Factory对象(尽管有名称)不是线程安全的。 and thus will require instantiating a new object per use (Do not do this other answer ).因此每次使用都需要实例化一个新对象(不要这样做其他答案)。

So for the first and second case I offer this gist: https://gist.github.com/3669307 which does what Lukas recommends .因此,对于第一种和第二种情况,我提供了这个要点: https ://gist.github.com/3669307 符合Lukas 的建议

For the third case you can either create basically a factory of a factory (which contains the DataSource ) or just instantiate a new Factory object in each method using the wired DataSource in your spring component.对于第三种情况,您可以基本上创建工厂的工厂(其中包含DataSource ),也可以使用 spring 组件中的有线DataSource在每个方法中实例化一个新的Factory对象。

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

As for the settings listener you can JOOQ's configuration support to avoid the programmatic creation.至于设置监听器,您可以通过 JOOQ 的配置支持来避免编程创建。

I won't cover how you setup a DataSource in Spring as that is covered in myriad of other/better places.我不会介绍如何在 Spring 中设置DataSource ,因为它在无数其他/更好的地方都有介绍。

Assuming you are using Spring to build a webapp, you probably want to be doing something like this:假设你正在使用 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
}

You probably want to be getting a DataSource via Spring's dependency injection, because your web container, Tomcat or whathaveyou, is providing the DataSource and doing connection pooling.您可能希望通过 Spring 的依赖注入获取 DataSource,因为您的 Web 容器 Tomcat 或其他任何东西都在提供 DataSource 并进行连接池。 In one of your spring config files you would have something like在你的一个弹簧配置文件中,你会有类似的东西

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>

The object that the above code is in (or some object that provides this code with the datasource) could have configuration in a spring file to instantiate it with the datasource, like上述代码所在的对象(或为该代码提供数据源的某个对象)可以在 spring 文件中配置以使用数据源实例化它,例如

<bean id="fooService" class="com.fubar.FooServiceImpl">
  <constructor-arg ref="dataSource" type="javax.sql.DataSource" />
</bean>

The portion of the string "jdbc/datasource" would correspond to a resource name configured in the web container.字符串“jdbc/datasource”的部分将对应于 Web 容器中配置的资源名称。 This varies, but for Tomcat it might be a context file in conf/Catalina/localhost under Tomcat home, for example,这会有所不同,但对于 Tomcat,它可能是 Tomcat 主页下 conf/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>

Hope this will be helpful for someone....希望这对某人有帮助....

Spring application context configuration. 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>

It will auto fill the public factory with the given connection (and yes, it can be a pooled connection, with auto close etc., see DriverManagerDataSource class for more detailed configuration).它将使用给定的连接自动填充公共工厂(是的,它可以是池连接,自动关闭等,请参阅 DriverManagerDataSource 类以获得更详细的配置)。 And now, the publicFactory.现在,publicFactory。 Note: no need to modify the original public factory generated by jOOQ.注意:不需要修改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);
    }
}

At the end, simply call the factory.最后,只需致电工厂即可。

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

Done!完毕!

For Java configuration (which is default for Spring Boot) you can use the following code:对于 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());
}

Easiest way,(I have found) to use Spring Transactions with jOOQ, is given here: http://blog.liftoffllc.in/2014/06/jooq-and-transactions.html最简单的方法,(我发现)将 Spring Transactions 与 jOOQ 一起使用,在这里给出: http ://blog.liftoffllc.in/2014/06/jooq-and-transactions.html

Have a look at this answer for better explanation: https://stackoverflow.com/a/24380508/542108看看这个答案以获得更好的解释: https ://stackoverflow.com/a/24380508/542108

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM