java 数据库编程 (一)
JDBC连接Sql Server数据库
一、JDBC简介
| java数据库连接技术(Java Database Connection,JDBC)是由java提供的一组与平台无关的数据库的操作标准,其本身由一类与接口组成,并且在操作中将按照严格的顺序执行。由于数据库属于资源操作,所以所有的数据库操作的最后必须要关闭数据库连接。 |
| |
| 下面为大家介绍JDBC的四种驱动,主要是为了普及一下知识,心急的小伙伴可以直接跳过,我们讲解的是JDBC本地驱动。 |
| |
1.JDBC-ODBC桥接技术
| Windows中的开放数据库连接(Open Database Connectivity,ODBC)是由微软提供的数据库编程接口。JDBC-ODBC桥接技术是先利用ODBC技术作为数据库的连接方式,再利用JDBC进行ODBC的连接,以实现数据库的操作。此类操作由于中间会使用ODBC,所以性能较差,但是此种方式不需要任何第三方开发包配置,所以使用较为方便。 |
2.JDBC本地驱动(本文讲解此方法)
| JDBC本地驱动是由不同的数据库生产商根据JDBC定义的操作标准实现各自的驱动程序,程序可以直接通过JDBC进行数据库的连接操作。该操作性能较高,但是需要针对不同的数据库配置与之匹配。 |
| |
3.JDBC网络驱动
| JDBC网络驱动将利用特定的数据库连接协议进行数据库的网络连接,这样可以连接任何一个指定服务器的数据库,使用起来较为灵活,在实际开发中被广泛使用。 |
| |
4.JDBC协议驱动
| JDBC协议驱动是利用JDBC提供的协议标准,将数据库的操作以特定的网络协议的方式进行处理。 |
| |
二、连接前配置
| 在连接数据库之前要进行一些Sql Server配置。 |
1.打开Sql Server配置管理器。
数据库版本 文件所在位置
Sql Server 2016 C:\Windows\SysWOW64\SQLServerManager13.msc
Sql Server 2014 C:\Windows\SysWOW64\SQLServerManager12.msc
Sql Server 2012 C:\Windows\SysWOW64\SQLServerManager11.msc
Sql Server 2008 C:\Windows\SysWOW64\SQLServerManager10.msc
根据上表种对应的版本找到相应文件的启动位置打开配置管理器。

也可以根据对应版本直接在微软小娜种搜索配置管理器名称,如:SQLServerManager10.msc 进行打开。

2.打开TCP/IP协议
找到你的Sql Server实例,双击打开TCP/IP协议,查看端口号。默认为1433,我的之前改过为1909。如果TCP/IP协议显示禁用,要将其启用。

3.修改Sql Server登陆设置
| 打开Sql Server,右击数据库实例名,点击属性,进入安全性选项。将服务器身份验证模式改为Ser Server和Windows验证模式(s)并修改超级管理员sa的密码,相信使用过Sql Server的小伙伴都进行过这项设置。以前改过的就可以跳过了。 |

找到安全性->登录名->sa,右键选择属性可以更改密码

然后选择状态,设置允许连接到数据库引擎

Sql Server配置到此结束,下面到微软官网下载所需JDBC库
https://www.microsoft.com/zh-CN/download/details.aspx?id=11774

解压后找到jre文件夹,如果你的JDK是1.80以上的就使用jre8里面的sqljdbc42.jar,如果是1.80以下的就使用jre7里面的sqljdbc41.jar
进入eclipse,右键当前工程文件,选择Properties,找到Java Build Path下面的Libraries,然后点击Add External JARs,根据JDK版本选择sqljdbc42.jar或sqljdbc41.jar,最后点击Apply And Close。连接前的配置工作到这里就结束了。

三、连接数据库
| 正如我们介绍JDBC时所说的,本篇文章针对的是本地驱动,因此需要先通过反射加载数据库驱动程序,然后通过DriverManager类根据指定的数据库连接地址、用户名、密码就可以取得数据库连接了。下面会在程序中详细介绍 |
| |
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| |
| public class Test02 { |
| |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| |
| 数据库名称DBMS |
| |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| System.out.println(conn); |
| } |
| } |
注:执行此代码时需保证Sql Server数据库是打开的并且已登陆,否则连谁呢
执行代码后输出以下字样则证明已连接成功,如果想了解更多数据库操作请阅读java数据库编程
(二) 数据库操作

java数据库编程(二) 数据库操作
今天首先为大家介绍一下数据库的连接及操作的核心类与接口,使大家对数据库操作有一个总体的把握,防止片面学习。
核心类和接口
名称 描述
Java.sql.DriverManagers类 提供数据库的驱动管理,主要负责数据库的连接对象取得
Java.sql.Connection接口 用于描述数据库的连接,并且可以通过此接口关闭连接
Java.sql.Statement接口 数据库的操作接口,通过连接对象打开
Java.sql.PreparedStatement接口 数据库预处理操作接口,通过连接对象打开
Java.sql.ResultSet接口 数据查询结果集描述,通过此接口获得查询结果
注:4个JDBC核心接口中都提供了close()方法,但是只要连接关闭,所有的操作就自然进行资源释放,因此只需要调用Connection接口的close()方法就可以释放全部资源。
1.Connection接口
| 用于取得数据库连接(为后续的数据库操作做准备)及资源的释放。 |
| |
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| public class ConnectionTest { |
| |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| |
| |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| System.out.println(conn); |
| conn.close(); |
| } |
| } |
2.Statement接口
| 当取得了数据库连接对象后,就意味着可以进行数据库操作了,而数据库中的数据库操作可以使用Statement接口完成。 |
| 如果要取得Statement接口的实例化对象则需要依靠Connection接口提供的方法完成。 |
Statement
序号 名称 描述
1 public Statement createStatement() throws SQLException 取得Statement接口对象
2 public int executeUpdate(String sql) throws SQLException 数据更新,返回影响行数
3 public ResultSet executeQuery(String sql) throws SQLException 数据查询,返回ResultSet结果集
(a)创建表
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.Statement; |
| |
| public class Test01 { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| |
| String createTable = "CREATE TABLE book(id int PRIMARY KEY IDENTITY(1,1)," |
| + "title varchar(25) NOT NULL," |
| + "price DECIMAL)"; |
| int len = statement.executeUpdate(createTable); |
| System.out.println("建表成功,影响的数据行数:" + len); |
| conn.close(); |
| |
| } |
| |
| } |
执行成功后可以到SQL Server中的DBMS数据库中看到book表且其内部为空。

(b)添加数据
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.Statement; |
| |
| public class AddTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| String sql = "INSERT INTO book(title,price) VALUES('Effective',88)"; |
| int len = statement.executeUpdate(sql); |
| System.out.println("插入成功,影响的数据行数:" + len); |
| sql = "INSERT INTO book(title,price) VALUES('java第一行代码',79.8)"; |
| len = statement.executeUpdate(sql); |
| System.out.println("插入成功,影响的数据行数:" + len); |
| sql = "INSERT INTO book(title,price) VALUES('Android第一行代码',77)"; |
| len = statement.executeUpdate(sql); |
| System.out.println("插入成功,影响的数据行数:" + len); |
| conn.close(); |
| |
| } |
| } |
执行成功后显示
因为每次只插入一条数据,所以每次只影响1行。刷新后到SQL Server中重新打开book表可以看到插入的数据
注:右键表名->编辑前200行可以看到上图中图形化的表
(c)更新数据
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| |
| public class UpdataTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| String sql = "UPDATE book set price=79 where title='Android第一行代码'"; |
| int len = statement.executeUpdate(sql); |
| System.out.println("修改数据,影响的数据行数:" + len); |
| conn.close(); |
| } |
| |
| } |
打开SQL Server中的book表,可以发现Android第一行代码的价格从77变为79

(d)删除数据
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.Statement; |
| |
| public class DeleteTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| String sql = "DELETE FROM book WHERE title='Effective'"; |
| int len = statement.executeUpdate(sql); |
| System.out.println("删除数据,影响的数据行数:" + len); |
| conn.close(); |
| } |
| } |
对比删除前后的book表,注意此时只剩下id为2和3的记录


(e)查询数据
通过代码发现上面几种操作方式基本无异,都是获取Statement对象之后,调用其executeUpdate()方法执行SQL语句。查询操作稍有不同,也不过是把executeUpdate()方法改为executeQuery()方法,并且使用ResultSet进行接收。
在java.sql.ResultSet接口里面定义了一下两种方法。
ResultSet
序号 名称 描述
1 public boolean next() throws SQLException 向下移动指针并判断是否有数据行
2 getInt()、getDouble()、getString()、getDate() 取出不同类型的数列内容
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.ResultSet; |
| import java.sql.Statement; |
| |
| public class QueryTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| String sql = "SELECT * FROM book"; |
| ResultSet rs = statement.executeQuery(sql); |
| while(rs.next()) { |
| String title = rs.getString("title"); |
| double price = rs.getDouble("price"); |
| System.out.println(title + "-->" + price); |
| } |
| conn.close(); |
| } |
| } |

如果感觉每次都要通过属性列名称查询比较麻烦还可以通过以下方式查询
| String sql = "SELECT * FROM book"; |
| ResultSet rs = statement.executeQuery(sql); |
| while(rs.next()) { |
| int index = rs.getInt(1); |
| String title = rs.getString(2); |
| double price = rs.getDouble(3); |
| System.out.println(index + "\t" + title + "\t" + price); |
| } |
| 输出结果,知识输出的时候控制格式不同而已,输出的数据是一样的。 |
| |

3.PreparedStatement接口
| 我们在实际的开发中绝大多数会只用拼凑SQL语句的方式进行数据库操作,如果变量中含有”’”或者“”“等用于定义数据库操操作语句的符号的话,必定会产生错误,而其在变量中又很难对其进行转义。为了解决Statement接口中的这种缺陷,就引入了PreparedStatement接口。 |
| PreparedStatement属于Statement的子接口,但是如果要取得该子接口的实例化对象,依然需要使用Connection所提供的方法:public PreparedStatement preparedStatement(String sql) throws SQLException。 |
| 此方法需要传入一个SQL语句,这个SQL是一个具备特殊标记的完整SQL,但是此时没有内容,所有的内容都会以占位符“?“的形式出现,而当取得了PreparedStatement接口对象后需要使用一系列setXxx()方法为指定编号(根据”?”从1开始排序)的占位符设置具体内容。 |


| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.PreparedStatement; |
| import java.sql.Statement; |
| |
| public class PreparedStatementTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| String sql = "INSERT INTO book(title,price) VALUES(?,?)"; |
| |
| PreparedStatement preparedStatement = conn.prepareStatement(sql); |
| preparedStatement.setString(1, "Effective java"); |
| preparedStatement.setDouble(2, 39); |
| int len = preparedStatement.executeUpdate(); |
| System.out.println("插入成功,影响的数据行数:" + len); |
| |
| conn.close(); |
| |
| } |
| } |
| 通过代码发现其实和Statement用法没有太大区别,只是多了占位符而已。学过SQL的小伙伴肯定对占位符再熟悉不过了,插入数据正常。 |
批处理与事务处理
所谓批处理指的是一次性向数据库中发出多条操作命令,而后所有的SQL语句将一起执行。在Statement接口与PreparedStatement接口中都有关于批处理的操作。
Statement接口定义的方法:
增加批处理语句:public void addBatch(String sql) throws SQLException
执行批处理:public int[] executeBatch() throws SQLException
PreparedStatement接口定义的方法
增加批处理语句:public void addBatch(String sql) throws SQLException
执行批处理:public int[] executeBatch() throws SQLException
执行批处理(以Statement接口为例)
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Arrays; |
| |
| public class Test { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| |
| statement.addBatch("INSERT INTO book(title,price) VALUES('Effective',88)"); |
| statement.addBatch("INSERT INTO book(title,price) VALUES('java第一行代码',79.8)"); |
| statement.addBatch("INSERT INTO book(title,price) VALUES('Effective',88)"); |
| |
| int[] results = statement.executeBatch(); |
| System.out.println("插入成功,影响的行数分别为:" + Arrays.toString(results)); |
| |
| conn.close(); |
| |
| } |
| } |
在正常情况下批处理描述的一定是一组关联的SQL操作,而如果执行多条更新语句中有一条语句出现了错误,那么理论上所有的语句都不应该被更新。不过默认情况下在错误语句之前的SQL更新都会正常执行,而出错之后的信息并不会执行。为了实现对批量处理操作的支持,可以使用事务来进行控制。
JDBC提供事务处理来进行手工的事务控制,所有的操作方法都在Connection接口里定义。
事务
序号 名称 描述
1 public void commit() throws SQLException 事务提交
2 public void rollback() throws SQLException 事务回滚
3 public void setAutoCommit(boolean autoCommit)
throws SQLException 设置是否为自动提交
利用事务处理
| package com.tjut.test; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Arrays; |
| |
| public class BatchTest { |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "1097542073"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| Statement statement = conn.createStatement(); |
| conn.setAutoCommit(false); |
| try { |
| |
| statement.addBatch("INSERT INTO book(title,price) VALUES('Effective java',88)"); |
| statement.addBatch("INSERT INTO book(title,price) VALUES('java第一行代码',79.8)"); |
| statement.addBatch("INSERT INTO book(title,price) VALUES('Android第一行代码',88)"); |
| |
| int[] results = statement.executeBatch(); |
| System.out.println("插入成功,影响的行数分别为:" + Arrays.toString(results)); |
| conn.commit(); |
| } catch (SQLException e) { |
| e.printStackTrace(); |
| conn.rollback(); |
| } |
| conn.close(); |
| |
| } |
| } |
读取ms sqlserver数据内容 示例如下:
| package pkg; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| |
| import java.sql.ResultSet; |
| import java.sql.PreparedStatement; |
| |
| import java.util.Date; |
| import java.text.SimpleDateFormat; |
| |
| public class Main { |
| |
| private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; |
| |
| |
| private static final String DBURL = "jdbc:sqlserver://localhost:1433;databaseName=fkxt"; |
| private static final String USER = "sa"; |
| private static final String PASSWORD = "Wsyqjjxt-Pass-9"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| Class.forName(DBDRIVER); |
| |
| Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD); |
| |
| |
| |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| String str1 = "2021-01-01"; |
| String str2 = "2021-01-31"; |
| Date starDate = sdf.parse(str1); |
| Date endDate = sdf.parse(str2); |
| String sql = "SELECT * FROM htxx where htrq between ? and ? "; |
| PreparedStatement preparedStatement = conn.prepareStatement(sql); |
| preparedStatement.setString(1, sdf.format(starDate)); |
| preparedStatement.setString(2, sdf.format(endDate)); |
| ResultSet rs = preparedStatement.executeQuery( ); |
| |
| while(rs.next()) { |
| String htbh = rs.getString("htbh"); |
| Date htrq = rs.getDate("htrq"); |
| double htbz = rs.getDouble("htsl"); |
| System.out.println(htbh + " --> "+ sdf.format(htrq) +" --> " + htbz); |
| } |
| conn.close(); |
| } |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了