一个JDBC
测试工具,用于执行数据库操作并处理结果
简要概述
这段代码展示了如何在Scala中使用JDBC进行数据库操作,并通过面向对象的方式封装和处理操作结果。
代码中的to方法用于类型转换,允许从泛型Three对象转换为具体的子类对象。
具体阐述
包和对象定义:
包名为recovery.scala,包含一个名为JdbcTest的对象。
结果枚举:
Result枚举定义了三种可能的操作结果:异常(EX)、数据操作语言(DML)和数据查询语言(DQL)。
泛型类Three:
Three类是一个泛型类,它封装了操作结果,并提供了一个类型转换方法to。
异常类Ex:
Ex类继承自Three,用于封装异常信息。
DML结果类Dml:
Dml类继承自Three,用于封装DML操作影响的行数。
DQL结果类Dql:
Dql类继承自Three,用于封装DQL操作返回的ResultSet。
数据库操作函数:
jdbc函数接受数据库连接参数和SQL语句,执行相应的数据库操作,并返回Three类型的结果。
主函数:
main函数演示了如何使用jdbc函数执行DML和DQL操作,并处理结果。
数据库连接和SQL执行:
在jdbc函数中,首先装载JDBC驱动,创建数据库连接,然后根据SQL语句类型执行对应的操作。
参数化查询:
如果提供了参数,使用PreparedStatement设置参数。
结果处理:
根据SQL语句的类型,返回相应的Dml或Dql对象,或者在出现异常时返回Ex对象。
DQL结果生成:
Dql类的generate方法用于从ResultSet生成Scala集合。
测试示例:
代码中提供了DML和DQL操作的示例,以及如何将DQL结果转换为自定义的Test对象的集合。
package recovery.scala
import java.sql._
import scala.collection.mutable.ArrayBuffer
object JdbcTest {
object Result extends Enumeration{
val EX = Value(0)
val DML = Value(1)
val DQL = Value(2)
}
case class Three(rst:Result.Value){
// 需要限制 T 的上限
def to[T<:Three]():T = this.asInstanceOf[T]
}
class Ex(throwable: Throwable) extends Three(Result.EX){
def ex = throwable
}
object Ex{
def apply(throwable: Throwable): Ex = new Ex(throwable)
}
class Dml(affectedRows:Int) extends Three(Result.DML){
def updated = affectedRows
}
object Dml{
def apply(affectedRows: Int): Dml = new Dml(affectedRows)
}
class Dql(set:ResultSet) extends Three(Result.DQL){
def generate[T](f:ResultSet=>T) ={
val buffer:ArrayBuffer[T] = ArrayBuffer()
while (set.next()) {
buffer.append(f(set))
}
buffer
}
}
object Dql{
def apply(set: ResultSet): Dql = new Dql(set)
}
def jdbc(url:String,user:String,pass:String)(sql:String,params:Seq[Any]=null):Three={
def con() = {
// 1.1 装载驱动
Class.forName("com.mysql.cj.jdbc.Driver")
// 1.2 创建连接对象
DriverManager.getConnection(url,user,pass)
}
def pst(con:Connection)={
// 2.1 创建执行对象
val pst: PreparedStatement = con.prepareStatement(sql)
// 2.2 初始化 SQL 参数
if(null != params && params.length>0){
params.zipWithIndex.foreach(t=>pst.setObject(t._2+1,t._1))
}
pst
}
try{
val connect: Connection = con()
val prepared: PreparedStatement = pst(connect)
sql match {
case sql if sql.matches("^(insert|INSERT|delete|DELETE|update|UPDATE) .*")
=>Dml(prepared.executeUpdate())
case sql if sql.matches("^(select|SELECT) .*")
=> Dql(prepared.executeQuery())
case _ => Ex(new SQLException(s"illegal sql command : $sql"))
}
}catch {
case e:Exception => Ex(e)
}
}
def main(args: Array[String]): Unit = {
// 解决结果差异化(正常和异常)
// import scala.util.control.Exception.{allCatch,failAsValue}
// 分段(参数列表)提取以复用
val operate: (String, Seq[Any]) => Three = jdbc(
url = "jdbc:mysql://single01:3306/test_db_for_bigdata",
user = "root",
pass = "ybremote"
)
/**
* mysql 资源包依赖:pom.xml
* 1.初始化
* driver: com.mysql.cj.jdbc.Driver
* url, username, password
* 创建连接
* 2.初始化执行器
* sql, parameters
* 创建执行器[,并初始化参数]
* 3.执行操作并返回【结果】
* DML:影响数据库表行数
* DQL:集合
* Exception:异常
*/
val dml : Dml = operate(
"insert into test_table1_for_hbase_import values(?,?,?,?,?)",
Seq(3012,"国庆节",75,"男","18014499655")
).to[Dml]
println(dml.updated)
val dml : Dml = operate(
"delete from test_table1_for_hbase_import where test_id between ? and ?",
Seq(1,10)
).to[Dml]
println(dml.updated)
val dql : Dql = operate(
"select * from test_table1_for_hbase_import limit 20",
null
).to[Dql]
case class Test(id:Int,name:String,age:Int,gender:String,phone:String)
val tests: ArrayBuffer[Test] = dql.generate[Test](rst => Test(
id = rst.getInt(1),
name = rst.getString(2),
age = rst.getInt(3),
gender = rst.getString(4),
phone = rst.getString(5)
))
tests.foreach(println)
}
}