参考:https://segmentfault.com/a/1190000006748584?utm_source=tuicool&utm_medium=referral
JOOQ 是基于Java访问关系型数据库的工具包。JOOQ 既吸取了传统ORM操作数据的简单性和安全性,又保留了原生sql的灵活性,它更像是介于 ORMS和JDBC的中间层。对于喜欢写sql的码农来说,JOOQ可以完全满足你控制欲,可以是用Java代码写出sql的感觉来。就像官网说的那样 :
get back in control of your sql
1.Springboot整合jooq首先加入jar包依赖
mysql mysql-connector-java 5.1.41 com.zaxxer HikariCP 2.6.2 org.jooq jooq 3.9.1
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/modeo?useUnicode=true&characterEncoding=UTF-8&useSSL=false username: modeo password: 123456
2.在项目根目录下建立一个文件夹generator目录下加入以下jar包以及建立mysql.xml(一会用到)
3.编辑mysql.xml文件
xml version="1.0" encoding="UTF-8" standalone="yes"?>xmlns="http://www.jooq.org/xsd/jooq-codegen-3.8.0.xsd"> com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/admin root 123456 org.jooq.util.JavaGenerator org.jooq.util.mysql.MySQLDatabase admin .* org.test.jooq.generated src/main/java/
^(.*)$ PASCAL $1 PASCAL $1_P_O
4.创建MysqlManager数据库操作工具
public class MysqlManager implements Closeable { private static final String DB_DRIVER_NAME = "spring.datasource.driver-class-name"; private static final String DB_URL = "spring.datasource.url"; private static final String DB_USERNAME = "spring.datasource.username"; private static final String DB_PASSWORD = "spring.datasource.password"; /** * Singleton */ private static final MysqlManager INSTANCE = new MysqlManager(); /** * database configuration */ private Configuration configuration = null; /** * database source */ private HikariDataSource dataSource = null; /** * get DSL context * * @return DSLContext */ public DSLContext getContext() { return DSL.using(this.configuration); } /** * Constructor */ private MysqlManager() { this.dataSource = new HikariDataSource(); this.dataSource.setDriverClassName(Config.getProperty(DB_DRIVER_NAME)); this.dataSource.setJdbcUrl(Config.getProperty(DB_URL)); this.dataSource.setUsername(Config.getProperty(DB_USERNAME)); this.dataSource.setPassword(Config.getProperty(DB_PASSWORD)); // 设置连接池的最大/最小 size this.dataSource.addDataSourceProperty("maxConnectionsPerPartition", "5"); this.dataSource.addDataSourceProperty("minConnectionsPerPartition", "1"); this.dataSource.addDataSourceProperty("idleConnectionTestPeriodInMinutes", "10"); this.dataSource.addDataSourceProperty("maxConnectionAgeInSeconds", "3600"); this.dataSource.addDataSourceProperty("idleMaxAgeInMinutes", "300"); this.dataSource.addDataSourceProperty("cachePrepStmts", "true"); this.dataSource.addDataSourceProperty("prepStmtCacheSize", "250"); this.dataSource.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); this.dataSource.addDataSourceProperty("connectionTimeout", "3000"); TransactionAwareDataSourceProxy proxy = new TransactionAwareDataSourceProxy(this.dataSource); DataSourceTransactionManager txMgr = new DataSourceTransactionManager(this.dataSource); this.configuration = new DefaultConfiguration().set(new DataSourceConnectionProvider(proxy)) .set(new SpringTransactionProvider(txMgr)).set(SQLDialect.MYSQL); } /** * Singleton * * @return instance */ public static MysqlManager getInstance() { return INSTANCE; } /** * transaction *做事物处理时用 * @param runnable */ public static void transaction(Runnable runnable) { DSLContext context = MysqlManager.getInstance().getContext(); context.transaction(config -> runnable.run()); } /** * Closes this stream and releases any system resources associated * with it. If the stream is already closed then invoking this * method has no effect. * *As noted in {@link AutoCloseable#close()}, cases where the * close may fail require careful attention. It is strongly advised * to relinquish the underlying resources and to internally * mark the {@code Closeable} as closed, prior to throwing * the {@code IOException}. * * @throws IOException if an I/O error occurs */ @Override public void close() throws IOException { if (this.dataSource != null && !this.dataSource.isClosed()) { this.dataSource.close(); this.dataSource = null; } this.configuration = null; } }
5.在linux系统下在创建的generator目录下运行以下命令就会生成数据库表对应的操作对象(在mysql.xml配置的路径下)
cd generator java -classpath jooq-3.9.1.jar:jooq-meta-3.9.1.jar:jooq-codegen-3.9.1.jar:mysql-connector-java-5.1.41.jar:. org.jooq.util.GenerationTool mysql.xml
6.具体的数据库操作案例:
(1.)使用事物处理
private static boolean removeSubscribedSymbol(String deviceId, ListexchangeSymbols) { if (exchangeSymbols == null || exchangeSymbols.isEmpty()) { return true; } DSLContext context = MysqlManager.getInstance().getContext(); GuestSubscribeMarket table = GuestSubscribeMarket.GUEST_SUBSCRIBE_MARKET; MysqlManager.transaction(() -> { for (MarketSymbolVO item : exchangeSymbols) { context.deleteFrom(table).where(table.DEVICE_ID.eq(deviceId), table.TYPE.eq(item.getType()), table.TARGET_ID.eq(item.getId())).execute(); } }); return true; }
(2)一般的操作
public static boolean hasSubscribedSymbol(String deviceId) { DSLContext context = MysqlManager.getInstance().getContext(); GuestSubscribeMarket table = GuestSubscribeMarket.GUEST_SUBSCRIBE_MARKET; return context.selectFrom(table).where(table.DEVICE_ID.eq(deviceId)).fetchAny() != null; }
(3)jooq支持纯sql的模式
/** * @param period * @param coinId * @return */ public static ListlistCoinKlineDO(String period, int coinId) { DSLContext context = MysqlManager.getInstance().getContext(); LocalDate localDate = LocalDate.now(ZoneId.of("GMT")); Date now = Date.valueOf(localDate); String sql = "select * from " + DEFAULT_COIN_KLINE_TABLE + period + " where `coin_id` = ? and `date` <= ? order " + "by `date` desc limit 240"; List records = context.fetch(sql, coinId, now); return records.stream().map(record -> { CoinKlineDO item = new CoinKlineDO(); item.setAmount((String) record.getValue("amount")); item.setOpen((String) record.getValue("open")); item.setHigh((String) record.getValue("high")); item.setLow((String) record.getValue("low")); item.setClose((String) record.getValue("close")); item.setTime(((Date) record.getValue("date")).getTime()); return item; }).collect(Collectors.toList()); }
/** * add record * * @param table * @param pairId * @param item * @return */ public static boolean addRecord(String table, int pairId, MarketKlineDO item) { DSLContext context = MysqlManager.getInstance().getContext(); InsertQuery> query = context.insertQuery(DSL.table(table)); query.addValue(DSL.field("`pair_id`", Integer.class), pairId); query.addValue(DSL.field("`time`", Timestamp.class), new Timestamp(item.getTime())); query.addValue(DSL.field("`open`", String.class), item.getOpen()); query.addValue(DSL.field("`high`", String.class), item.getHigh()); query.addValue(DSL.field("`low`", String.class), item.getLow()); query.addValue(DSL.field("`close`", String.class), item.getClose()); query.addValue(DSL.field("`amount`", String.class), item.getAmount()); query.addValue(DSL.field("`create_at`", Timestamp.class), new Timestamp(System.currentTimeMillis())); return query.execute() > 0; }
/** * add record * * @param table * @param pairId * @param items * @return */ public static boolean addRecords(String table, int pairId, Listitems) { final boolean[] addRet = {true}; MysqlManager.transaction(() -> { for (MarketKlineDO item : items) { boolean ret = addRecord(table, pairId, item); if (!ret) { addRet[0] = false; break; } } }); return addRet[0]; }