Scala应用 —— JDBC的创建

在这里插入图片描述
在这里插入图片描述

文章目录

  • Scala应用 —— JDBC的创建
      • 前言
      • 一、JDBC的创建过程
          • 1.初始化连接
            • 1.1 配置驱动
            • 1.2 创建连接对象
          • 2. 初始化执行器
            • 2.1 创建执行器对象
            • 2.2 初始化执行器参数
          • 3. 执行操作并返回结果
      • 二、Scala JDBC的基本设计思路
          • 1. 操作步骤设计
          • 2. 解决结果差异化
          • 3.实现jdbc方法并输出结果
      • 三、代码汇总与结果
          • 1. 代码
          • 2.结果

Scala应用 —— JDBC的创建

前言

该文章旨在通过Scala语言实现JDBC的创建,以熟悉Scala语言的使用。

一、JDBC的创建过程

1.初始化连接
1.1 配置驱动

在pom.xml中打入以下依赖,向项目中打入MySQL JDBC驱动

<!-- MySQL 驱动 -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version>
</dependency>

该语句用于加载MySQL JDBC驱动。

Class.forName("com.mysql.cj.jdbc.Driver")
1.2 创建连接对象

参数:url,username,password

2. 初始化执行器

执行器的创建需要依赖连接对象,因此先初始化连接再初始化执行器。

2.1 创建执行器对象

参数:sql,parameters

2.2 初始化执行器参数
3. 执行操作并返回结果
  • DML:影响数据库的表行数
  • DQL:List
  • Exception:异常

二、Scala JDBC的基本设计思路

JDBC的创建实际上就是包含了两个操作步骤和一个多返回类型设计的小型化任务。

1. 操作步骤设计
def jdbc(url:String,username:String,password:String)(sql:String,params:Seq[Any]=null):Unit{}
  • 多操作过程可以写成柯里化的形式,不仅实现了参数分组,同时还隐含了一种参数间的依赖关系

  • params不一定会有,并且可能同时包含多种不同的数据类型。

    因此可以通过可变参数T*或者序列Seq[T]的方式进行表示。

    同时,默认情况下不传参,因此指定一个默认值为null

    • Any*
    • Seq[Any]
2. 解决结果差异化

结果类型包括:

  • DML:影响数据库的表行数
  • DQL:List
  • Exception:异常

JDBC的结果类型包含了两种正常类型和一种异常类型,自带的OptionEitherTry都无法满足这种需求,我们的解决方式如下:

  1. 首先定义了一个名为ResultType的枚举类型,它包含三个值:EX,DQLDML
  2. 定义了一个抽象类Three,它包含了一个类型为ResultType.Value的构造参数,这个参数用来表示具体的结果类型。此处选择抽象类是因为需要传递一个构造参数,这种设计允许在继承Three的子类中具体化不同类型的结果处理(差异化处理)。
  3. 三个样例类(Ex,DML,和 DQL)继承自抽象类 Three,每个样例类都对应一个 ResultType 的值,并封装了与其类型相关的数据。
object ResultType extends Enumeration{val EX,DQL,DML = Value
}abstract class Three(val rst:ResultType.Value)case class Ex(throwable: Throwable) extends Three(ResultType.EX){def ex = throwable
}case class DML(affectedRows:Int) extends Three(ResultType.DML){def updated = affectedRows
}case class DQL(set: ResultSet) extends Three(ResultType.DQL){/*** 为什么要将(f:ResultSet=>T)独立为一个方法的参数?* 减少不必要的类型约束,不需要每次创建DQL对象都需要指定泛型。* */def generate[T](f:ResultSet=>T)(implicit ct:ClassTag[T])={val buffer:ArrayBuffer[T] = ArrayBuffer()// 遍历结果集(包含由一次查询返回的所有行),用f将结果集的每一行转化为一个实体while (set.next()) {buffer.append(f(set))}buffer.toArray}
}
3.实现jdbc方法并输出结果
  • 基类通过asInstanceOf[T]的方法实现向具体子类的转化
  • id = rst.getInt(1)这类语句是通过字段序号代替了字段名称
    在这里插入图片描述
def jdbc(url: String, username: String, password: String)(sql: String, params: Seq[Any] = null): Three = {def conn(): Connection = {// 1.1 装载驱动Class.forName("com.mysql.cj.jdbc.Driver")// 1.2 创建连接对象val conn: Connection = DriverManager.getConnection(url, username, password)conn}def pst(conn: Connection): PreparedStatement = {// 2.1 创建执行对象val pst: PreparedStatement = conn.prepareStatement(sql)// 2.2 设置sql配置为(序号,参数)的格式if (null != params && params.nonEmpty) {params.zipWithIndex.foreach {// 设置执行对象对应的SQL语句`?`对应的占位符。case (param, index) => pst.setObject(index + 1, param)}}pst}try {val connect: Connection = connval statement: PreparedStatement = pst(connect)// 过程级增删改查(数据记录):INSERT DELETE UPDATE SELECT// 对象级增删改查(对象——表、视图、索引):CREATE DROP ALTER SHOWsql match {case sql if sql.matches("SELECT|select") => DQL(statement.executeQuery())case sql if sql.matches("INSERT|insert|DELETE|delete|UPDATE|update") => DML(statement.executeUpdate())// 处理SQL语句异常case _ => Ex(new SQLException(s"illegal sql command:$sql"))}} catch {// 其他异常case e: Exception => Ex(e)}
}def main(args: Array[String]): Unit = {val dql: DQL = jdbc(url = "jdbc:mysql://single01:3306/test_db_for_bigdata",username = "root",password = "123456")(sql = "SELECT * FROM test_table1_for_hbase_import LIMIT 20").asInstanceOf[DQL]// 将结果集对应的字段设置为样例类,自动生成getter方法case class Test(id: Int, name: String, age: Int, gender: String, phone: String)// 将结果集的每一行转化为一个Test对象val tests: Array[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)
}

三、代码汇总与结果

1. 代码
package recoveryimport java.sql.{Connection, DriverManager, PreparedStatement, ResultSet, SQLException}
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTagobject JDBCTest2 {object ResultType extends Enumeration{val EX,DQL,DML = Value}abstract class Three(val rst:ResultType.Value)case class Ex(throwable: Throwable) extends Three(ResultType.EX){def ex = throwable}case class DML(affectedRows:Int) extends Three(ResultType.DML){def updated = affectedRows}case class DQL(set: ResultSet) extends Three(ResultType.DQL){/*** 为什么要将(f:ResultSet=>T)独立为一个方法的参数?* 减少不必要的类型约束,不需要每次创建DQL对象都需要指定泛型。* */def generate[T](f:ResultSet=>T)(implicit ct:ClassTag[T])={val buffer:ArrayBuffer[T] = ArrayBuffer()// 遍历结果集(包含由一次查询返回的所有行),用f将结果集的每一行转化为一个实体while (set.next()) {buffer.append(f(set))}buffer.toArray}}def jdbc(url: String, username: String, password: String)(sql: String, params: Seq[Any] = null): Three = {def conn(): Connection = {// 1.1 装载驱动Class.forName("com.mysql.cj.jdbc.Driver")// 1.2 创建连接对象val conn: Connection = DriverManager.getConnection(url, username, password)conn}def pst(conn: Connection): PreparedStatement = {val pst: PreparedStatement = conn.prepareStatement(sql)if (null != params && params.nonEmpty) {params.zipWithIndex.foreach {// 设置执行对象对应的SQL语句`?`对应的占位符。case (param, index) => pst.setObject(index + 1, param)}}pst}try {val connect: Connection = connval statement: PreparedStatement = pst(connect)// 过程级增删改查(数据记录):INSERT DELETE UPDATE SELECT// 对象级增删改查(对象——表、视图、索引):CREATE DROP ALTER SHOWsql match {case sql if sql.matches("SELECT|select") => DQL(statement.executeQuery())case sql if sql.matches("INSERT|insert|DELETE|delete|UPDATE|update") => DML(statement.executeUpdate())case _ => Ex(new SQLException(s"illegal sql command:$sql"))}} catch {case e: Exception => Ex(e)}}def main(args: Array[String]): Unit = {val result = jdbc(url = "jdbc:mysql://single01:3306/test_db_for_bigdata",username = "root",password = "123456")(sql = "SELECT * FROM test_table1_for_hbase_import LIMIT 20;")result match {case dql: DQL =>case class Test(id: Int, name: String, age: Int, gender: String, phone: String)val tests: Array[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)case ex: Ex =>println("Error occurred: " + ex.ex.getMessage)}}
2.结果

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/318110.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析

在浏览器中渲染大尺寸 3D 模型&#xff1a;Speckle 处理空间抖动的方法 WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析 注: 相机空间和视图空间 概念等效混用 1、实现的关键代码 const material new THREE.RawShaderMaterial({uniforms: {cameraPostion: {…

《十二》Qt各种对话框之FileDialog文件对话框及QMessageBox 消息对话框

QFileDialog 对话框 选择打开一个文件 若要打开一个文件&#xff0c;可调用静态函数 QFileDialog::getOpenFileName()&#xff0c;“打开一个文件”按钮的响应代码如下&#xff1a; void Dialog::on_btnOpen_clicked() { //选择单个文件QString curPathQDir::currentPath()…

React | React.cloneElement 的使用

我看到同事的代码里有 cloneElement&#xff0c;于是去了解了一下这个函数。 就跟它的名字一样&#xff0c;克隆元素&#xff0c;可以基于一个元素创建一个新的元素&#xff0c;并且为新元素添加新的属性或者覆盖已有的属性。 下面是一个简单例子&#xff1a; .node1 {backg…

PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

TD工程介绍 我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展&#xff0c;可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容&#xff0c;只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可&#xff0c;主要修我以…

Apache Seata基于改良版雪花算法的分布式UUID生成器分析2

title: 关于新版雪花算法的答疑 author: selfishlover keywords: [Seata, snowflake, UUID, page split] date: 2021/06/21 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 关于新版雪花算法的答疑 在上一篇关于新版雪花算法的解析中…

Hive优化以及相关参数设置

1.表层面设计优化 1.1 表分区 分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹&#xff0c;该文件夹下是该分区所有的数据文件。Hive 中的分区就是分目录&#xff0c;把一个大的数据集根据业务需要分割成小的数据集。在查询时通过 WHERE 子句中的表达式选择查询所需要…

Apache Seata基于改良版雪花算法的分布式UUID生成器分析1

title: Seata基于改良版雪花算法的分布式UUID生成器分析 author: selfishlover keywords: [Seata, snowflake, UUID] date: 2021/05/08 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Seata基于改良版雪花算法的分布式UUID生成器分析…

10.JAVAEE之网络编程

1.网络编程 通过网络,让两个主机之间能够进行通信 >基于这样的通信来完成一定的功能进行网络编程的时候,需要操作系统给咱们提供一组 AP1, 通过这些 API才能完成编程&#xff08;API 可以认为是 应用层 和 传输层 之间交互的路径&#xff09;&#xff08;API:Socket API相当…

NDK 基础(一)—— C 语言知识汇总

本系列文章主要是介绍一些 NDK 开发所需的基础知识&#xff0c;目录如下&#xff1a; NDK 基础&#xff08;一&#xff09;—— C 语言知识汇总 NDK 基础&#xff08;二&#xff09;—— C 语言基础与特性1 NDK 基础&#xff08;三&#xff09;—— C 语言基础与特性2 NDK 基础…

比较美观即将跳转html源码

源码介绍 比较美观即将跳转html源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 源码截图 比较美观的一个跳转界面&#xff0c;修改方法如上&…

FreeRTOS-系统时钟节拍和时间管理

一、前言 任何操作系统都需要提供一个时钟节拍&#xff0c;以供系统处理诸如延时&#xff0c;超时等与时间相关的事件。时钟节拍是特定的周期性中断&#xff0c; 这个中断可以看做是系统心跳。 中断之间的时间间隔取决于不同的应用&#xff0c;一般是 1ms – 100ms。时钟的节拍…

【C++ —— 多态】

C —— 多态 多态的概念多态的定义和实现多态的构成条件虚函数虚函数的重写虚函数重写的两个例外协变&#xff1a;析构函数的重写 C11 override和final重载、覆盖(重写)、隐藏(重定义)的对比 抽象类概念接口继承和实现继承 多态的继承虚函数表多态的原理动态绑定和静态绑定 单继…

BERT一个蛋白质-季军-英特尔创新大师杯冷冻电镜蛋白质结构建模大赛-paipai

关联比赛: “创新大师杯”冷冻电镜蛋白质结构建模大赛 解决方案 团队介绍 paipai队、取自 PAIN AI&#xff0c;核心成员如我本人IvanaXu(IvanaXu GitHub)&#xff0c;从事于金融科技业&#xff0c;面向银行信用贷款的风控、运营场景。但我们团队先后打过很多比赛&#xf…

算法系列--BFS解决拓扑排序

&#x1f495;"请努力活下去"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–算法系列–BFS解决拓扑排序 大家好,今天为大家带来的是算法系列--BFS解决拓扑排序 前言:什么是拓扑排序 拓扑排序–解决有顺序的排序问题(要做事情的先后顺序) …

docker各目录含义

目录含义builder构建docker镜像的工具或过程buildkit用于构建和打包容器镜像&#xff0c;官方构建引擎&#xff0c;支持多阶段构建、缓存管理、并行化构建和多平台构建等功能containerd负责容器生命周期管理&#xff0c;能起、停、重启&#xff0c;确保容器运行。负责镜管理&am…

Java设计模式 _结构型模式_组合模式

一、组合模式 1、组合模式 组合模式&#xff08;Composite Pattern&#xff09;是这一种结构型设计模式。又叫部分整体模式。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次关系。即&#xff1a;创建了一个包含自己对象组的类&#xff0c;该类提供了修改…

Idea报错:无法访问org.springframework.boot.SpringApplication

在开发项目时&#xff0c;常常会遇到这种问题&#xff0c;报错信息如下图所示 版本号与jdk版本号存在对应关系&#xff0c;61.0对应jdk17&#xff0c;52.0对应jdk8 所以是某个依赖的版本太高&#xff0c;降低该依赖的版本即可 具体步骤&#xff1a; ①修改pom.xml中spring b…

ASP.NET实验室预约系统的设计

摘 要 实验室预约系统的设计主要是基于B/S模型&#xff0c;在Windows系统下&#xff0c;运用ASP.NET平台和SQLServer2000数据库实现实验室预约功能。该设计主要实现了实验室的预约和管理功能。预约功能包括老师对实验室信息、实验项目和实验预约情况的查询以及对实验室的预约…

ubuntu系统搭建pytorch环境详细步骤【笔记】

实践设备&#xff1a;华硕FX-PRO&#xff08;NVIDIA GeForce GTX 960M&#xff09; 搭建PyTorch环境的详细步骤如下&#xff1a; 1.安装Ubuntu系统&#xff1a; 下载Ubuntu的镜像文件并制作启动盘。将启动盘插入计算机&#xff0c;启动计算机并按照提示安装Ubuntu系统。 2.…

Linux内核之原子操作:atomic_long_dec用法实例(六十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…