Druid+Sqlite-JDBC+Kotlin,封装的一个都是毛病的工具类,奆佬们,评论区教一下我怎么封装
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,封装的一个都是毛病的工具类,奆佬们,评论区教一下我怎么封装相关推荐
- 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil
基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...
- Android基于Retrofit2.0 +RxJava 封装的超好用的RetrofitClient工具类(六)
csdn :码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51958010 RetrofitClient 基于Retrofit2 ...
- 微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人
微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人. 该工具类主要是对dozer进行了封装,使用过程代码量极少,废话少说,贴代码了 import j ...
- 微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人...
微服务应用大行其道,我提供一个dto和entity转换工具类,方便大家做转换,少写机械代码,多陪陪家人. 该工具类主要是对dozer进行了封装,使用过程代码量极少,废话少说,贴代码了 import j ...
- java图片缩放工具类,一个JAVA图形缩放处置工具类
一个JAVA图形缩放处理工具类 调用的例子 import java.io.FileOutputStream; import java.io.IOException; import javax.imag ...
- 封装各种生成唯一性ID算法的工具类
/*** Copyright (c) 2005-2012 springside.org.cn** Licensed under the Apache License, Version 2.0 (the ...
- 分享一个发送http请求的工具类
分享一个发送http请求的工具类 maven依赖只需要导入一个 <dependencies><dependency><groupId>commons-httpcli ...
- Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出
前言 如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类. 我直接一把梭,嘎嘎给你一顿导出. 我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题. 我也跟他们说了,但是他们就是 ...
- [HDF5] 封装了一个简单的C++ HDF5工具库,实现常用数据类型的读写
目录 一.开发环境 二.主要功能 三.文件结构 四.HDF5写数据到hdf5文件功能实现 五.HDF5读hdf5文件数据到程序中数据结构功能实现 六.头文件Hdf5Function.h 七.工具类 八 ...
最新文章
- 求第k小元素:采用特定分治策略
- 提高sql性能的方法
- 计算文本相似度_Python文本相似性计算
- [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第51篇]什么是基于ID的加密的安全模型,描述一个IBE方案
- 计算机网络第4版潘爱民_王道考研 计算机网络(2)学习笔记
- 全球首个AI协同及大数据安全标准正在制定,创新工场参与推进
- 在bash中,如何检查字符串是否以某个值开头?
- 欧拉筛(bzoj 2818: Gcd)
- [20180423]表空间闪回与snapshot standby
- Kepserver如何连接InTouch
- Leaflet加turf生成等值线图(或色斑图)并单击显示值
- 学生成绩排名预测(DC)
- asp.net实现无刷新ajax技术登录界面
- 糜烂性胃炎吃什么药?
- 【python基础知识学习(6)】面向对象编程
- 使用JAVA Apache POI对图片进行裁剪展示
- 读的, 且经过美化, 能在所有 JavaScript 环境中运行, 并且应该和对应手写的 JavaScript 一样快或者更快.
- 【数据增强】Cutout
- B端产品经理如何快速了解并分析陌生领域的产品
- java struts2模板,Struts2 主题和模板
热门文章
- 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数014,tuple,元组
- woo 语言最简单的生成验证码方式,是个人都能看懂,反正比py简单多了
- ifstream fin
- 常见Java面试+答案
- matlab解决相遇追及问题,猎犬追狐狸试题中追击时间问题的严格求解.doc
- moment 获得上月开始日期和结束日期
- Ping++和BeeCloud的比较
- python人脸识别门禁_树莓派人脸识别门禁系统图文教程
- 五大方案,教你关于微信公众号的内容定位
- 2006年中国互联网天使投资大会文字实录