Druid+JDBC工具类
我只是一个新手,也不怎么会kotlin但是我看教程都很少,讲SQLite-JDBC结合Druid或者说怎么写Durid的配置文件,

我先放工具类

import com.alibaba.druid.pool.DruidDataSourceFactory
import java.io.FileInputStream
import java.io.InputStream
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.sql.*
import java.util.*
import javax.sql.DataSourceclass JdbcUtil {//数据源连接池对象private var dataSource: DataSource? = null//ThreadLocal 对象private var threadLocal: ThreadLocal<Connection>? = nullprivate constructor() {try {val inputStream: InputStream = FileInputStream("db.properties")val prop: Properties = Properties()prop.load(inputStream)//使用Druid连接池方式dataSource = DruidDataSourceFactory.createDataSource(prop)threadLocal = ThreadLocal()} catch (e: Exception) {throw RuntimeException("加载配置文件出错!${e.message}")}}@Throws(SQLException::class)fun getConnection(): Connection? {//从当前线程获取Connectionvar connection: Connection? = this.threadLocal!!.get()if (connection == null) {//如果没有就从连接池获取connection = dataSource?.connection//添加到ThreadLocalthis.threadLocal?.set(connection)}return connection}companion object {@Volatileprivate var instance: JdbcUtil? = nullfun getInstance() = instance ?: synchronized(this) {instance ?: JdbcUtil().also { instance = it }}}/*** 封装的通用增删改方法* @param sql 需要操作的SQL语句* @param params 执行SQL语句时需要的参数*/private fun update(sql: String, vararg params: Any = emptyArray()): Int {var connection: Connection? = nullvar statement: PreparedStatement? = nulltry {connection = getConnection()statement = connection?.prepareStatement(sql)if (params.isNotEmpty()) {for (i in params.indices) {statement?.setObject(i + 1, params[i])}}return statement!!.executeUpdate()} catch (e: Exception) {e.printStackTrace()} finally {destroy(connection, statement, null)}return 0}fun executeUpdate(sql: String): Int {return update(sql)}fun executeUpdateBoolean(sql: String): Boolean {val result: Int = update(sql)if (result > 0) {return true}return false}fun executeUpdate(sql: String, vararg params: Any): Int {return update(sql, params)}fun getPreparedStatement(sql: String): PreparedStatement {return getConnection()!!.prepareStatement(sql)}fun executeUpdateBoolean(sql: String, vararg params: Any): Boolean {val result: Int = update(sql, params)if (result > 0) {return true}return false}/*** 查询多条数据的封装方法* @param clazz 结果的封装对象* @param sql 要执行的SQL语句* @param params 执行SQL语句时需要的参数* @param <T> 消费金融泛型类型* @return 返回查询的结果集*/fun <T> query(sql: String, clazz: Class<T>, vararg params: Any): List<T> {var connection: Connection? = nullvar statement: PreparedStatement? = nullvar rs: ResultSet? = nullvar entities: List<T>?try {connection = getConnection()statement = connection!!.prepareStatement(sql)for (i in params.indices) {statement?.setObject(i + 1, params[i])}rs = statement.executeQuery()entities = mutableListOf()//获取ResultSet对象来获取元数据信息val meteData: ResultSetMetaData = rs.metaDataval columnCount: Int = meteData.columnCountwhile (rs.next()) {val entity: T = clazz.getDeclaredConstructor().newInstance()for (i in 1..columnCount) {val columnLabel: String = meteData.getColumnLabel(i)val field: Field = clazz.getDeclaredField(columnLabel)field.isAccessible = truefield.set(entity, rs.getObject(columnLabel))}entities.add(entity)}return entities} catch (e: Exception) {e.printStackTrace()throw RuntimeException("查询多条数据时出错,错误信息为:${e.message}")} finally {destroy(connection, statement, rs)}}//                entity = if (clazz == Int::class.java) {//                    val constructor: Constructor<T> = clazz.getDeclaredConstructor(Int::class.javaPrimitiveType)
//                    constructor.newInstance(rs.getInt(1))
//                } else if (clazz == Long::class.java) {//                    val constructor: Constructor<T> = clazz.getDeclaredConstructor(Long::class.javaPrimitiveType)
//                    constructor.newInstance(rs.getLong(1))
//                } else {//                    throw RuntimeException("参数中能传 int 类型或 long 类型。")
//                }/*** 查询多条数据的封装方法* @param clazz 结果的封装对象* @param sql 要执行的SQL语句* @param params 执行SQL语句时需要的参数* @param <T> 消费金融泛型类型* @return 返回查询的结果</T> */fun <T> queryForObject(clazz: Class<T>, sql: String?, vararg params: Any?): T? {var conn: Connection? = nullvar pstm: PreparedStatement? = nullvar rs: ResultSet? = nullvar entity: T? = nulltry {conn = getConnection()pstm = conn!!.prepareStatement(sql)for (i in params.indices) {pstm.setObject(i + 1, params[i])}rs = pstm.executeQuery()val metaData: ResultSetMetaData = rs.metaDatawhile (rs.next()) {entity = when (clazz) {Int::class -> {val constructor: Constructor<T> = clazz.getDeclaredConstructor(Int::class.java)constructor.newInstance(rs.getInt(1))}Long::class -> {val constructor: Constructor<T> = clazz.getDeclaredConstructor(Long::class.java)constructor.newInstance(rs.getLong(1))}else -> {throw RuntimeException("参数可以转换int或者long")}}}return entity} catch (e: Exception) {e.printStackTrace()throw RuntimeException("统计查询时出错,错误信息为:" + e.message)} finally {destroy(conn, pstm, rs)}}private fun destroy(connection: Connection?, statement: PreparedStatement?, rs: ResultSet?) {connection?.close()statement?.close()rs?.close()}}

这两个随便借鉴,我都感觉有问题,我太菜了

import java.io.File
import java.io.FileInputStream
import java.lang.reflect.Field
import java.net.URL
import java.sql.*
import java.util.*
import kotlin.collections.ArrayListclass SQLiteUtils {//磁盘文件路劲名 dbprivate var path: String? = null// 操作链接private var connection: Connection? = null//语法执行层private var statement: Statement? = null//连接数据库的信息private var user = ""private var password = ""private var url = ""private var driver = ""private constructor(path: String) {this.path = pathconnection = getConnection(path)}/*** 把JDBC返回的结果集封装成特定类型* @Author: fangju* @Date: 2019/6/15*/interface IResultSetHandler<T> {@Throws(Exception::class)fun handle(rs: ResultSet): T?}//Kotlin 可带参数的检测锁模式companion object {@Volatileprivate var instance: SQLiteUtils? = nullfun getInstance(path: String) = instance ?: synchronized(this) {instance ?: SQLiteUtils(path).also { instance = it }}}@Throws(SQLException::class)fun getStatement(): Statement? {if (this.statement == null) {this.statement = this.connection!!.createStatement()}return this.statement}/*** 获取Sqlite操作链接** @param path sqlite数据表,为磁盘文件名* @return*/@Throws(SQLException::class, ClassNotFoundException::class)private fun getConnection(path: String?): Connection? {var connection: Connection? = nullClass.forName("org.sqlite.JDBC")if (path!!.endsWith(".db")) {connection = DriverManager.getConnection("jdbc:sqlite:$path")}return connection}/*** 增删改操作* @param sql 传入的SQL语句* @param params 可变参数* @return 操作结果*//* 在kotlin变长参数中 * 叫 spread操作,可以理解为“打散”,“分散”*/fun executeUpdate(sql: String, vararg params: Any): Int {var preparedStatement: PreparedStatement? = nullvar result: Int = 0try {preparedStatement = connection?.prepareStatement(sql)//给预编译语句赋值for (i in params.indices) {preparedStatement?.setObject(i + 1, params[i])}//执行SQL语句,获取执行结果result = preparedStatement!!.executeUpdate()} catch (e: SQLException) {e.printStackTrace()} finally {preparedStatement?.close()}return result}fun <T> executeQuery(sql: String, handler: IResultSetHandler<T>, vararg params: Any): T? {var preparedStatement: PreparedStatement? = nullvar rs: ResultSet? = nullvar connection: Connection? = nulltry {connection = this.connectionpreparedStatement = connection?.prepareStatement(sql)for (i in params.indices) {preparedStatement!!.setObject(i + 1, params[i])}rs = preparedStatement!!.executeQuery()return handler.handle(rs)} catch (e: Exception) {e.printStackTrace()} finally {preparedStatement?.close()rs?.close()connection?.close()}return null}fun executeDML(sql: String, vararg params: Any): Boolean {var connection: Connection? = nullvar statement: PreparedStatement? = nulltry {connection = getConnection(path)statement = connection?.prepareStatement(sql)for (i in params.indices) {statement?.setObject(i + 1, params[i])}val resultCode: Int = statement!!.executeUpdate()if (resultCode > 0) {return true}} catch (e: Exception) {e.printStackTrace()} finally {connection?.close()statement?.close()}return false}//获取连接的方法private fun getConnection(): Connection? {var connection: Connection? = nulltry {//通过反射获取配置文件位置val resource: URL? = SQLiteUtils::class.java.getResource("/")val filePath = File(resource!!.file)val files: Array<File> = filePath.listFiles()var configFile: File? = null //配置文件路径for (file in files) {if (!file.isDirectory) //不是文件夹{if (file.name.equals("mysql.properties")) //文件名为mysql.properties{configFile = File(file.path) //确定配置文件}}}if (configFile == null) { //如果没有mysql.properties配置文件就抛出异常throw java.lang.Exception("小老弟,检查检查配置文件mysql.properties有没有")}//        通过Properties读取配置文件val properties = Properties()properties.load(FileInputStream(configFile))//        获取连接数据库的信息user = properties.getProperty("user")password = properties.getProperty("password")url = properties.getProperty("url")driver = properties.getProperty("driver")// 获取数据库连接Class.forName(driver) //加载驱动connection = DriverManager.getConnection(url, user, password)} catch (e: java.lang.Exception) {e.printStackTrace()}return connection}/*** 通用的查询方法** @param sql    要执行的sql语句* @param clazz  对应的实体类* @param params 条件参数(?对应的值)* @param <T>    对应的实体类型* @return</T> *///    T表示集合中使用的泛型,Class<T> clazz就是对应的实体类fun <T> executeDQL(sql: String?, clazz: Class<T>, vararg params: Any?): List<T>? {var connection: Connection? = null//PreparedStatement 是 Statement 的子类,它的一大好处是可以防止 SQL 注入var statement: PreparedStatement? = nullvar resultSet: ResultSet? = nullvar list: List<T>? = null //存放实体类的集合try {connection = getConnection() //获取连接statement = connection!!.prepareStatement(sql) //执行sql语句//            设置参数,如果params不为空说明要设置参数for (i in params.indices) {//从第一位开始对应赋值statement.setObject(i + 1, params[i])}resultSet = statement.executeQuery() //获取结果集//        可以通过ResultSet获取当前有那些列val metaData = resultSet.metaData //元数据,可以通过它获取表中的列//        获取表中列的总数val columnCount = metaData.columnCount//            用来存放我们查询的信息对应的实体类list = ArrayList()//判断是否有记录,然后再根据列名获取每列的信息while (resultSet.next()) { //每次循环获取的是一列数据//我们现在不能确定传入的实体类,这里用泛型替代,当你传入实体类型时确定val t = clazz.getDeclaredConstructor().newInstance()for (i in 1..columnCount)  //循环要从1开始{ //遍历列数,获取每一列的名字val columnLabel = metaData.getColumnLabel(i) //列名//                通过列名获取对应列的数据val `object` = resultSet.getObject(columnLabel)//                    通过列名获取实体类中的属性名val field: Field = clazz.getDeclaredField(columnLabel)//                    给获取的实体类的属性赋值field.isAccessible = true //取消安全检查field.set(t, `object`) //给t对象设置从数据库中查询出来的object值field.isAccessible = false //开启安全检查}list.add(t) //把得到的实体类存入集合}} catch (e: java.lang.Exception) {e.printStackTrace()} finally {//关闭连接close(connection, statement, resultSet)}return list //返回实体类集合}private fun close(connection: Connection?, statement: Statement?, resultSet: ResultSet?) {try {connection?.close()statement?.close()resultSet?.close()} catch (e: Exception) {e.printStackTrace()}}@Throws(SQLException::class)fun executeUpdate(sql: String) {getStatement()?.executeUpdate(sql)}@Throws(SQLException::class)private fun releaseConnection() {if (this.connection != null || this.connection!!.isClosed) {this.connection!!.close()this.connection = null}if (this.statement != null) {this.statement!!.close()this.statement = null}}}

我是在网上找大佬写的,我只是把代码转成kotlin并改成了单例模式,我也很少写文章,懒。不能保证这个工具类有没有问题,我对kotlin的反射还不是很了解,希望大家可以评论区留言,

db.properties


druid.driverClassName=org.sqlite.JDBC
druid.url=jdbc:sqlite:test.db
druid.validationQuery=SELECT 1
druid.testWhileIdle=true
druid.testOnBorrow=false
druid.testOnReturn=false

如上配置之后,运行项目idea终端会抛出

5月 10, 2022 6:43:09 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited

百度了一圈,没什么解决办法,
反正项目运行之后会在C:\Users\WuXiangGuJun\IdeaProjects\SQLite-JDBC\test.db


在idea中双击test.db可以打开数据库文件

这是刚刚创建的数据库,当然这些列是我自己搞的

Druid+Sqlite-JDBC+Kotlin,封装的一个都是毛病的工具类,奆佬们,评论区教一下我怎么封装相关推荐

  1. 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

    基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...

  2. Android基于Retrofit2.0 +RxJava 封装的超好用的RetrofitClient工具类(六)

    csdn :码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51958010 RetrofitClient 基于Retrofit2 ...

  3. 微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人

    微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人. 该工具类主要是对dozer进行了封装,使用过程代码量极少,废话少说,贴代码了 import j ...

  4. 微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人...

    微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人. 该工具类主要是对dozer进行了封装,使用过程代码量极少,废话少说,贴代码了 import j ...

  5. java图片缩放工具类,一个JAVA图形缩放处置工具类

    一个JAVA图形缩放处理工具类 调用的例子 import java.io.FileOutputStream; import java.io.IOException; import javax.imag ...

  6. 封装各种生成唯一性ID算法的工具类

    /*** Copyright (c) 2005-2012 springside.org.cn** Licensed under the Apache License, Version 2.0 (the ...

  7. 分享一个发送http请求的工具类

    分享一个发送http请求的工具类 maven依赖只需要导入一个 <dependencies><dependency><groupId>commons-httpcli ...

  8. Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出

    前言 如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类. 我直接一把梭,嘎嘎给你一顿导出. 我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题. 我也跟他们说了,但是他们就是 ...

  9. [HDF5] 封装了一个简单的C++ HDF5工具库,实现常用数据类型的读写

    目录 一.开发环境 二.主要功能 三.文件结构 四.HDF5写数据到hdf5文件功能实现 五.HDF5读hdf5文件数据到程序中数据结构功能实现 六.头文件Hdf5Function.h 七.工具类 八 ...

最新文章

  1. 求第k小元素:采用特定分治策略
  2. 提高sql性能的方法
  3. 计算文本相似度_Python文本相似性计算
  4. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第51篇]什么是基于ID的加密的安全模型,描述一个IBE方案
  5. 计算机网络第4版潘爱民_王道考研 计算机网络(2)学习笔记
  6. 全球首个AI协同及大数据安全标准正在制定,创新工场参与推进
  7. 在bash中,如何检查字符串是否以某个值开头?
  8. 欧拉筛(bzoj 2818: Gcd)
  9. [20180423]表空间闪回与snapshot standby
  10. Kepserver如何连接InTouch
  11. Leaflet加turf生成等值线图(或色斑图)并单击显示值
  12. 学生成绩排名预测(DC)
  13. asp.net实现无刷新ajax技术登录界面
  14. 糜烂性胃炎吃什么药?
  15. 【python基础知识学习(6)】面向对象编程
  16. 使用JAVA Apache POI对图片进行裁剪展示
  17. 读的, 且经过美化, 能在所有 JavaScript 环境中运行, 并且应该和对应手写的 JavaScript 一样快或者更快.
  18. 【数据增强】Cutout
  19. B端产品经理如何快速了解并分析陌生领域的产品
  20. java struts2模板,Struts2 主题和模板

热门文章

  1. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数014,tuple,元组
  2. woo 语言最简单的生成验证码方式,是个人都能看懂,反正比py简单多了
  3. ifstream fin
  4. 常见Java面试+答案
  5. matlab解决相遇追及问题,猎犬追狐狸试题中追击时间问题的严格求解.doc
  6. moment 获得上月开始日期和结束日期
  7. Ping++和BeeCloud的比较
  8. python人脸识别门禁_树莓派人脸识别门禁系统图文教程
  9. 五大方案,教你关于微信公众号的内容定位
  10. 2006年中国互联网天使投资大会文字实录