JOOQ和Spring

发布于 2024-10-08 19:10:49 字数 111 浏览 6 评论 0原文

有没有人尝试过将 JOOQ 与 Spring 框架一起使用,或者我正在开辟新天地?

http://www.jooq.org

Has anyone tried using JOOQ with the Spring framework or am I breaking new ground?

http://www.jooq.org

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

怪我入戏太深 2024-10-15 19:10:49

许多人将 jOOQ 与 Spring 或 Spring Boot 结合使用

Petri Kainulainen 还提供了一个非常好的教程,解释了设置项目的每个步骤,此处:

这是一篇关于如何在 Spring Boot 中使用 jOOQ 的博客文章,当您需要jOOQ 的商业发行版:

Many people are using jOOQ with Spring or Spring Boot

There is also a very good tutorial by Petri Kainulainen, explaining every step to set up a project, here:

Here's a blog post about how to use jOOQ with Spring Boot, especially useful when you need the commercial distributions of jOOQ:

三生池水覆流年 2024-10-15 19:10:49

我希望使用 jOOQ 作为构建器库来提供对 Spring 的 JdbcTemplate 和相关类的查询。不幸的是,jOOQ 似乎将两个概念组合到同一组类中:SQL 生成和查询执行。就我而言,我想要前者,但想让 Spring 处理后者。不过,它确实有效。例如,您可以执行以下操作(使用 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);

I was looking to use jOOQ as an builder library for providing queries to Spring's JdbcTemplate and related classes. Unfortunately, jOOQ appears to combine two concepts into the same set of classes: SQL generation and query execution. In my case, I want the former but want to let Spring handle the latter. It does work, though. For example, you can do something like this (using 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);
伴我老 2024-10-15 19:10:49

使用 jOOQ 运行 spring 事务要简单得多(除非我忘了什么):

只需将数据源包装到

org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy

可选中:延迟打开 jdbc 连接,直到第一个实际的 sql 语句发生,使用

org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy

so 作为示例这样做是为了创建一个应用了“事务”和“惰性”的 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!

getting spring transactions running with jOOQ is a lot simpler (unless I forgot something):

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

org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy

so as an sample do this to create a jOOQ factory with 'transactions' and 'lazyness' applied

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!
爱的那么颓废 2024-10-15 19:10:49

要使 jOOQ 与 spring 一起工作,您需要做/知道的所有事情:

  1. 获取由事务管理器绑定到线程的 java.sql.Connection
  2. 通过异常转换正确处理事务
  3. 了解 jOOQ Factory 对象(尽管有名称)不是线程安全的。因此每次使用都需要实例化一个新对象(不要这样做答案)。

因此,对于第一种和第二种情况,我提供以下要点: https://gist.github.com/3669307 它执行 Lukas 建议的操作

对于第三种情况,您可以基本上创建一个工厂的工厂(其中包含 DataSource),或者只是使用有线 在每个方法中实例化一个新的 Factory 对象。 Spring 组件中的 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 的配置支持来避免编程式创建。

我不会介绍如何在 Spring 中设置 DataSource,因为它在无数其他/更好的地方都有介绍。

All you need to do/know to make jOOQ work with spring:

  1. Get the java.sql.Connection bound to the thread by the transaction manager.
  2. Handle transactions properly through exception translation
  3. Understand that the jOOQ Factory objects (despite the name) are not threadsafe. 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.

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.

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

I won't cover how you setup a DataSource in Spring as that is covered in myriad of other/better places.

最单纯的乌龟 2024-10-15 19:10:49

希望这对某人有帮助......

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>

它将使用给定的连接自动填充公共工厂(是的,它可以是池连接,具有自动关闭等功能,请参阅 DriverManagerDataSource 类以获取更详细的配置)。
现在,publicFactory。注意:不需要修改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);
                }

完毕!

Hope this will be helpful for someone....

Spring application context configuration.

 <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).
And now, the publicFactory. Note: no need to modify the original public factory generated by 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!

随波逐流 2024-10-15 19:10:49

假设你正在使用 Spring 构建一个 Web 应用程序,你可能想要做这样的事情:

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
}

你可能想要通过 Spring 的依赖注入获取数据源,因为你的 Web 容器、Tomcat 或其他什么东西正在提供数据源并进行连接池。在你的一个 spring 配置文件中,你会有类似

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

上述代码所在的对象(或为该代码提供数据源的某个对象)可以在 spring 文件中进行配置,以使用数据源实例化它,

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

例如字符串“jdbc/datasource”将对应于 Web 容器中配置的资源名称。这会有所不同,但对于 Tomcat 来说,它可能是 Tomcat home 下的 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>

Assuming you are using Spring to build a webapp, you probably want to be doing something like this:

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. 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

<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. This varies, but for Tomcat it might be a context file in conf/Catalina/localhost under Tomcat home, for example,

<?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>
倾城月光淡如水﹏ 2024-10-15 19:10:49

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

For Java configuration (which is default for Spring Boot) you can use the following code:

/* 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());
}
萌面超妹 2024-10-15 19:10:49

(我发现)将 Spring Transactions 与 jOOQ 结合使用的最简单方法如下: http://blog.liftoffllc.in/2014/06/jooq-and-transactions.html

看看这个答案以获得更好的解释:https://stackoverflow.com/a/24380508/542108

Easiest way,(I have found) to use Spring Transactions with jOOQ, is given here: 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文