jOOQ和Spring很容易整合。 在這個例子中,咱們將整合:java
Alibaba Druid(但您也能夠使用其餘鏈接池,如BoneCP,C3P0,DBCP等)。mysql
Spring TX做爲事物管理library。git
jOOQ做爲SQL構建和執行library。spring
DROP TABLE IF EXISTS `author`; CREATE TABLE `author` ( `id` int(11) NOT NULL, `first_name` varchar(50) DEFAULT NULL, `last_name` varchar(50) NOT NULL, `date_of_birth` date DEFAULT NULL, `year_of_birth` int(11) DEFAULT NULL, `distinguished` int(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` int(11) NOT NULL, `author_id` int(11) NOT NULL, `title` varchar(400) NOT NULL, `published_in` int(11) NOT NULL, `language_id` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `book_store`; CREATE TABLE `book_store` ( `name` varchar(400) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `book_to_book_store`; CREATE TABLE `book_to_book_store` ( `name` varchar(400) NOT NULL, `book_id` int(11) NOT NULL, `stock` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `language`; CREATE TABLE `language` ( `id` int(11) NOT NULL, `cd` char(2) NOT NULL, `description` varchar(50) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `author` ADD PRIMARY KEY (`id`); ALTER TABLE `book` ADD PRIMARY KEY (`id`), ADD KEY `fk_book_author` (`author_id`), ADD KEY `fk_book_language` (`language_id`); ALTER TABLE `book_store` ADD UNIQUE KEY `name` (`name`); ALTER TABLE `book_to_book_store` ADD PRIMARY KEY (`name`,`book_id`), ADD KEY `fk_b2bs_book` (`book_id`); ALTER TABLE `language` ADD PRIMARY KEY (`id`);
在這個例子中,咱們將建立如下Maven依賴項:sql
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsyso</groupId> <artifactId>jooq-tutorials-2</artifactId> <packaging>jar</packaging> <name>jooq-tutorials-2</name> <version>1.0.0</version> <properties> <!-- spring --> <spring.version>4.1.9.RELEASE</spring.version> <!-- /spring --> <!-- environment --> <jdk.version>1.8</jdk.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <downloadSources>true</downloadSources> <slf4j.version>1.7.7</slf4j.version> <!-- /environment --> <!-- jdbc --> <mysql.driver.version>5.1.30</mysql.driver.version> <druid.version>1.0.18</druid.version> <!-- /jdbc --> <!-- jooq --> <jooq.version>3.9.5</jooq.version> <!-- /jooq --> </properties> <repositories> <repository> <id>aliyun-repos</id> <name>Aliyun Repository</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyun-repos</id> <name>Aliyun Repository</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </pluginRepository> </pluginRepositories> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.driver.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jooq</groupId> <artifactId>jooq</artifactId> <version>${jooq.version}</version> </dependency> <dependency> <groupId>org.jooq</groupId> <artifactId>jooq-meta</artifactId> <version>${jooq.version}</version> </dependency> <dependency> <groupId>org.jooq</groupId> <artifactId>jooq-codegen</artifactId> <version>${jooq.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- TEST begin --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!-- TEST end --> <!-- LOGGING begin --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- common-logging 實際調用slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!-- java.util.logging 實際調用slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!-- LOGGING end --> </dependencies> <build> <plugins> <!-- Compiler 插件, 設定JDK版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> <showWarnings>true</showWarnings> </configuration> </plugin> <!-- 打包jar文件時,配置manifest文件,加入lib包的jar依賴 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> </plugin> <!-- resource插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> </plugin> <!-- install插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <!-- clean插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> <version>2.6.1</version> </plugin> <!-- dependency插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.10</version> </plugin> <!-- 打包時跳過不執行測試用例 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> <developers> <developer> <id>com.jsyso</id> <name>Jan</name> <email>xujian_jason@163.com</email> <timezone>+8</timezone> </developer> </developers> </project>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd" default-lazy-init="true"> <description>Spring Configuration</description> <!-- 加載配置屬性文件 --> <context:property-placeholder ignore-unresolvable="true" location="classpath:config.properties" /> <!-- 數據源配置 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass --> <property name="driverClassName" value="${jdbc.driver}" /> <!-- 基本屬性 url、user、password --> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${jdbc.pool.init}" /> <property name="minIdle" value="${jdbc.pool.minIdle}" /> <property name="maxActive" value="${jdbc.pool.maxActive}" /> <!-- 配置獲取鏈接等待超時的時間 --> <property name="maxWait" value="60000" /> <!-- 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個鏈接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="${jdbc.testSql}" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 配置監控統計攔截的filters --> <property name="filters" value="stat" /> </bean> <!-- 定義事務 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置 Annotation 驅動,掃描@Transactional註解的類定義事務 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!-- 配置jOOQ的ConnectionProvider使用Spring的TransactionAwareDataSourceProx --> <bean id="transactionAwareDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <constructor-arg ref="dataSource" /> </bean> <bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider"> <constructor-arg ref="transactionAwareDataSource" /> </bean> <!-- 可選,重寫jOOQ異常,拋出Spring Exception --> <bean id="exceptionTranslator" class="test.generated.exception.ExceptionTranslator" /> <bean class="org.jooq.impl.DefaultConfiguration" name="config"> <property name="SQLDialect"><value type="org.jooq.SQLDialect">MYSQL</value></property> <property name="connectionProvider" ref="connectionProvider" /> <property name="executeListenerProvider"> <array> <bean class="org.jooq.impl.DefaultExecuteListenerProvider"> <constructor-arg index="0" ref="exceptionTranslator"/> </bean> </array> </property> </bean> <!-- 配置jOOQ的dsl對象 --> <bean id="dsl" class="org.jooq.impl.DefaultDSLContext"> <constructor-arg ref="config" /> </bean> </beans>
查詢測試:數據庫
package test.generated.service; import static java.util.Arrays.asList; import static org.jooq.impl.DSL.countDistinct; import static org.junit.Assert.assertEquals; import static test.generated.Tables.*; import org.jooq.DSLContext; import org.jooq.Record3; import org.jooq.Result; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import test.generated.tables.Author; import test.generated.tables.Book; import test.generated.tables.BookStore; import test.generated.tables.BookToBookStore; import test.generated.tables.records.BookRecord; /** * @author Lukas Eder */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/jooq-spring.xml"}) public class QueryTest { @Autowired DSLContext create; @Test public void testJoin() throws Exception { // All of these tables were generated by jOOQ's Maven plugin Book b = BOOK.as("b"); Author a = AUTHOR.as("a"); BookStore s = BOOK_STORE.as("s"); BookToBookStore t = BOOK_TO_BOOK_STORE.as("t"); Result<Record3<String, String, Integer>> result = create.select(a.FIRST_NAME, a.LAST_NAME, countDistinct(s.NAME)) .from(a) .join(b).on(b.AUTHOR_ID.eq(a.ID)) .join(t).on(t.BOOK_ID.eq(b.ID)) .join(s).on(t.NAME.eq(s.NAME)) .groupBy(a.FIRST_NAME, a.LAST_NAME) .orderBy(countDistinct(s.NAME).desc()) .fetch(); assertEquals(2, result.size()); assertEquals("Paulo", result.getValue(0, a.FIRST_NAME)); assertEquals("George", result.getValue(1, a.FIRST_NAME)); assertEquals("Coelho", result.getValue(0, a.LAST_NAME)); assertEquals("Orwell", result.getValue(1, a.LAST_NAME)); assertEquals(Integer.valueOf(3), result.getValue(0, countDistinct(s.NAME))); assertEquals(Integer.valueOf(2), result.getValue(1, countDistinct(s.NAME))); } }
數據插入,使用Spring的TransactionManager來顯式處理事務:apache
package test.generated.service; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static test.generated.Tables.BOOK; import java.util.concurrent.atomic.AtomicBoolean; import org.jooq.DSLContext; import org.junit.After; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; /** * @author Petri Kainulainen * @author Lukas Eder * * @see <a * href="http://www.petrikainulainen.net/programming/jooq/using-jooq-with-spring-configuration/">http://www.petrikainulainen.net/programming/jooq/using-jooq-with-spring-configuration/</a> */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/jooq-spring.xml"}) @TransactionConfiguration(transactionManager="transactionManager") public class TransactionTest { @Autowired DSLContext dsl; @Autowired DataSourceTransactionManager txMgr; @Test public void testDelBooks() { // Delete all books that were created in any test dsl.delete(BOOK).where(BOOK.ID.gt(4)).execute(); } @Test public void testAddBooks() { TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition()); for (int i = 1; i <= 6; i++) dsl.insertInto(BOOK) .set(BOOK.ID, i) .set(BOOK.PUBLISHED_IN, 1) .set(BOOK.LANGUAGE_ID, 1) .set(BOOK.AUTHOR_ID, 1) .set(BOOK.TITLE, "Book " + i) .execute(); txMgr.commit(tx); } @Test public void testExplicitTransactions() { boolean rollback = false; TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition()); try { // This is a "bug". The same book is created twice, resulting in a // constraint violation exception for (int i = 7; i <=9; i++) dsl.insertInto(BOOK) .set(BOOK.ID, i) .set(BOOK.AUTHOR_ID, 1) .set(BOOK.TITLE, "Book " + i) .execute(); Assert.fail(); } // Upon the constraint violation, we explicitly roll back the transaction. catch (DataAccessException e) { txMgr.rollback(tx); rollback = true; } assertEquals(4, dsl.fetchCount(BOOK)); assertTrue(rollback); } }
【jOOQ中文】教程代碼都會放在碼雲,但願多多宣傳給Star(^_−)☆。api