import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}
import org.apache.commons.pool2.impl.{DefaultPooledObject, GenericObjectPool, GenericObjectPoolConfig}
import org.apache.commons.pool2.{BasePooledObjectFactory, PooledObject}
import .business.tornado.event.esTokafka.model.EsExportRecord
import test.config.Constans
import test.util.PropertiesUtil
// 创建用于处理MySQL查询结果的类的抽象接口
trait QueryCallback {
def process(rs: ResultSet)
}
/**
* MySQL客户端代理对象
*
* @param jdbcUrl MySQL URL
* @param jdbcUser MySQL 用户
* @param jdbcPassword MySQL 密码
* @param client 默认客户端实现
*/
case class MySqlProxy(jdbcUrl: String, jdbcUser: String, jdbcPassword: String, client: Option[Connection] = None) {
// 获取客户端连接对象
private val mysqlClient = client getOrElse {
DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword)
}
/**
* 执行增删改SQL语句
*
* @param sql
* @param params
* @return 影响的行数
*/
def executeUpdate(sql: String, params: Array[Any]): Int = {
var rtn = 0
var pstmt: PreparedStatement = null
try {
// 第一步:关闭自动提交
mysqlClient.setAutoCommit(false)
// 第二步:根据传入的sql语句创建prepareStatement
pstmt = mysqlClient.prepareStatement(sql)
// 第三步:为prepareStatement中的每个参数填写数值
if (params != null && params.length > 0) {
for (i <- 0 until params.length) {
pstmt.setObject(i + 1, params(i))
}
}
// 第四步:执行增删改操作
rtn = pstmt.executeUpdate()
// 第五步:手动提交
mysqlClient.commit()
} catch {
case e: Exception => e.printStackTrace
}
rtn
}
/**
* 执行增删改SQL语句
*
* @param sql
* @param param
* @return 影响的行数
*/
def executeUpdate(sql: String, param: EsExportRecord): Int = {
var rtn = 0
var pstmt: PreparedStatement = null
try {
// 第一步:关闭自动提交
mysqlClient.setAutoCommit(false)
// 第二步:根据传入的sql语句创建prepareStatement
pstmt = mysqlClient.prepareStatement(sql)
// 第三步:为prepareStatement中的每个参数填写数值
pstmt.setString(1, param.fromTime)
pstmt.setString(2, param.toTime)
pstmt.setInt(3, param.count.toInt)
pstmt.setString(4, param.startTime)
pstmt.setString(5, param.endTime)
pstmt.setInt(6, param.ifNotSuccess)
pstmt.setString(7, param.eIndex)
// 第四步:执行增删改操作
rtn = pstmt.executeUpdate()
// 第五步:手动提交
mysqlClient.commit()
} catch {
case e: Exception => e.printStackTrace
}
rtn
}
/**
* 执行查询SQL语句
*
* @param sql
* @param params
*/
def executeQuery(sql: String, params: Array[Any], queryCallback: QueryCallback) {
var pstmt: PreparedStatement = null
var rs: ResultSet = null
try {
// 第一步:根据传入的sql语句创建prepareStatement
pstmt = mysqlClient.prepareStatement(sql)
// 第二步:为prepareStatement中的每个参数填写数值
if (params != null && params.length > 0) {
for (i <- 0 until params.length) {
pstmt.setObject(i + 1, params(i))
}
}
// 第三步:执行查询操作
rs = pstmt.executeQuery()
// 第四步:处理查询后的结果
queryCallback.process(rs)
} catch {
case e: Exception => e.printStackTrace
}
}
def executeQueryErrorRecord(sql: String, index: String): (String, Int) = {
var pstmt: PreparedStatement = null
var rs: ResultSet = null
try {
// 第一步:根据传入的sql语句创建prepareStatement
pstmt = mysqlClient.prepareStatement(sql)
// 第二步:为prepareStatement中的每个参数填写数值
pstmt.setString(1, index)
// 第三步:执行查询操作
rs = pstmt.executeQuery()
// 第四步:处理查询后的结果
rs.next()
(rs.getString(1), rs.getInt(2))
} catch {
case e: Exception => e.printStackTrace
null
}
}
/**
* 批量执行SQL语句
*
* @param sql
* @param paramsList
* @return 每条SQL语句影响的行数
*/
def executeBatch(sql: String, paramsList: Array[Array[Any]]): Array[Int] = {
var rtn: Array[Int] = null
var pstmt: PreparedStatement = null
try {
// 第一步:关闭自动提交
mysqlClient.setAutoCommit(false)
pstmt = mysqlClient.prepareStatement(sql)
// 第二步:为prepareStatement中的每个参数填写数值
if (paramsList != null && paramsList.length > 0) {
for (params <- paramsList) {
for (i <- 0 until params.length) {
pstmt.setObject(i + 1, params(i))
}
pstmt.addBatch()
}
}
// 第三步:执行批量的SQL语句
rtn = pstmt.executeBatch()
// 第四步:手动提交
mysqlClient.commit()
} catch {
case e: Exception => e.printStackTrace
}
rtn
}
// 关闭MySQL客户端
def shutdown(): Unit = mysqlClient.close()
}
/**
* 将MySqlProxy实例视为对象,MySqlProxy实例的创建使用对象池进行维护
*/
/**
* 创建自定义工厂类,继承BasePooledObjectFactory工厂类,负责对象的创建、包装和销毁
*
* @param jdbcUrl
* @param jdbcUser
* @param jdbcPassword
* @param client
*/
class PooledMySqlClientFactory(jdbcUrl: String, jdbcUser: String, jdbcPassword: String, client: Option[Connection] = None) extends BasePooledObjectFactory[MySqlProxy] with Serializable {
// 用于池来创建对象
override def create(): MySqlProxy = MySqlProxy(jdbcUrl, jdbcUser, jdbcPassword, client)
// 用于池来包装对象
override def wrap(obj: MySqlProxy): PooledObject[MySqlProxy] = new DefaultPooledObject(obj)
// 用于池来销毁对象
override def destroyObject(p: PooledObject[MySqlProxy]): Unit = {
p.getObject.shutdown()
super.destroyObject(p)
}
}
/**
* 创建MySQL池工具类
*/
object CreateMySqlPool {
// 加载JDBC驱动,只需要一次
Class.forName("com.mysql.jdbc.Driver")
// 在org.apache.commons.pool2.impl中预设了三个可以直接使用的对象池:GenericObjectPool、GenericKeyedObjectPool和SoftReferenceObjectPool
// 创建genericObjectPool为GenericObjectPool
// GenericObjectPool的特点是可以设置对象池中的对象特征,包括LIFO方式、最大空闲数、最小空闲数、是否有效性检查等等
private var genericObjectPool: GenericObjectPool[MySqlProxy] = null
// 伴生对象通过apply完成对象的创建
def apply(): GenericObjectPool[MySqlProxy] = {
// 单例模式
if (this.genericObjectPool == null) {
this.synchronized {
// 获取MySQL配置参数
val properties = PropertiesUtil.getProperties("common.properties")
val jdbcUrl: String = properties.get(Constans.JDBC_URL).toString
val jdbcUser = properties.get(Constans.JDBC_USER).toString
val jdbcPassword = properties.get(Constans.JDBC_PASSWORD).toString
val size = properties.get(Constans.JDBC_DATASOURCE_SIZE).toString.toInt
println("jdbc_url = " + jdbcUrl)
println("user = " + jdbcUser)
println("password = " + jdbcPassword)
println("number of connection" + size)
val pooledFactory = new PooledMySqlClientFactory(jdbcUrl, jdbcUser, jdbcPassword)
val poolConfig = {
// 创建标准对象池配置类的实例
val c = new GenericObjectPoolConfig
// 设置配置对象参数
// 设置最大对象数
c.setMaxTotal(size)
// 设置最大空闲对象数
c.setMaxIdle(size)
c
}
// 对象池的创建需要工厂类和配置类
// 返回一个GenericObjectPool对象池
this.genericObjectPool = new GenericObjectPool[MySqlProxy](pooledFactory, poolConfig)
}
}
genericObjectPool
}
}
来源:oschina
链接:https://my.oschina.net/thomas2/blog/3159954