java数据库编程(二) 数据库操作
关于数据库的连接方法已在java 数据库编程(一)JDBC连接Sql Server数据库一文中为大家介绍,还没有链接数据库的小伙伴请先点击查看。
今天首先为大家介绍一下数据库的连接及操作的核心类与接口,使大家对数据库操作有一个总体的把握,防止片面学习。
名称 | 描述 |
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 {//SQLServer本地驱动的地址private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";//连接sqlserver数据库;本地连接;通过1909号端口号连接(根据你自身数据库的端口号来),数据库名称DBMS//你需要现在Sql Server客户端上建立一个数据库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接口提供的方法完成。
序号 | 名称 | 描述 |
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();//建表语句,有id、title和price三个属性其中id是主键且设置为自增长。此句属于SQL语句,不懂的小伙伴可以照抄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接口里面定义了一下两种方法。
序号 | 名称 | 描述 |
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();//取得Statement对象String sql = "SELECT * FROM book";ResultSet rs = statement.executeQuery(sql);//使用ResultSet接收数据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 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();//关闭数据库连接}
}
最后,将数据库中存储的三本书推荐给大家。
- java 第一行代码 李兴华 马云涛
- Android 第一行代码 郭霖
- Effective java 作者国外的,记不清楚名字
这几本书写得都非常非常的好,声明一遍,没有商业关系,没有商业关系,没有商业关系。单纯的写得好,想推荐给大家。
java数据库编程(二) 数据库操作相关推荐
- Java网络编程(二) 连续发送数据
有了建立连接的基础后,接下来尝试连续地发送和接收数据. 对于发送端比较好理解,有数据时就可以发送出去.对于接收端,就需要一直监听是否有数据发送过来.一个基本的方法就是使用 while(true) 循环 ...
- mysql 数据库编程_MySQL数据库编程(C++语言)
MySQL数据库编程(C++语言) 发布时间:2018-05-24 21:06, 浏览次数:452 , 标签: MySQL 本文主要介绍使用C++语言连接和操作 MySQL 数据库的方法. 1. 准备 ...
- Java 并发编程(二):如何保证共享变量的原子性?
线程安全性是我们在进行 Java 并发编程的时候必须要先考虑清楚的一个问题.这个类在单线程环境下是没有问题的,那么我们就能确保它在多线程并发的情况下表现出正确的行为吗? 我这个人,在没有副业之前,一心 ...
- 数据库 数据库编程二
//头文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unis ...
- C#增删改查操作Access数据库之二(数据库的增加)
功能:添加四个TextBox控件,在这四个控件中分别输入要添加的ID,学号,姓名,年龄,性别信息,单击Insert按钮将数据添加到Access数据库中并通过datagridview显示添加后的数据库. ...
- Java并发编程(二十三)------并发设计模式之生产者消费者模式
参考文章:Java实现生产者消费者问题与读者写者问题 目录 1. 生产者消费者问题 1.1 wait() / notify()方法 1.2 await() / signal()方法 1.2.1 对sy ...
- Java网络编程二:Socket详解
Socket又称套接字,是连接运行在网络上两个程序间的双向通讯的端点. 一.使用Socket进行网络通信的过程 服务端:服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端的连接 ...
- java并发编程(二十六)——单例模式的双重检查锁模式为什么必须加 volatile?
前言 本文我们从一个问题出发来进行探究关于volatile的应用. 问题:单例模式的双重检查锁模式为什么必须加 volatile? 什么是单例模式 单例模式指的是,保证一个类只有一个实例,并且提供一个 ...
- 【Java 并发编程】线程操作原子性问题 ( 问题业务场景分析 | 使用 synchronized 解决线程原子性问题 )
文章目录 总结 一.原子性问题示例 二.线程操作原子性问题分析 三.使用 synchronized 解决线程原子性问题 总结 原子操作问题 : 线程中 , 对变量副本 count 进行自增操作 , 不 ...
最新文章
- sqlite复制数据主键重复_Flutter 数据库指南
- IKAnalyzer使用停用词词典进行分词
- 随机生成颜色和透明度
- 日常生活小技巧 -- vim 中 ctags 的安装和使用
- 在查询语句中使用 NOLOCK 和 READPAST
- 【Linux】一步一步学Linux——uname命令(72)
- 查询优化器内核剖析第四篇:从一个实例看执行计划
- frontcon函数用不了_C++复制构造函数与析构函数
- CVPR 2020 | 中科院、商汤联合提出大规模多标签目标检测新算法
- c++连接mysql的中文编码问题
- ELK下Elasticsearch如何关掉服务
- Excel中 对「对话气泡(吹き出し)」中的文字添加删除线 等操作
- Spring Cloud之Swagger集群搭建
- 【GDB调试学习笔记】Makefile多级目录生成多个可执行文件
- 心电图分析软件_动态心电图品牌排行榜
- RemObjects Elements 11.0
- layerdate一款很好用日期插件
- 有生之年转ta系列 美术部分 1.1 美术理论基础
- Day4-STM32的中断与通信——百问网7天物联网智能家居
- Microsoft Teams通话质量仪表盘(CQD)怎么玩?
热门文章
- 爆料:我的「盐值」狂掉 100 分与其背后的秘密
- 哪里可以学计算机优化编程,【计算机专业论文】计算机编程课程实践教学优化(共3825字)...
- 大连爱在海边儿童村第三期电子杂志draft
- MATLAB R2014b 的安装破解
- 英特尔处理器能够用鸿蒙系统吗,华为下月发布新型电脑,非英特尔、AMD平台,或将搭载鸿蒙系统?...
- Jpa操作数据库之动态SQL语句的使用
- 详解RPC框架核心原理
- 网管宝典 电脑故障排除之“八先八后”
- 数学建模之Python-BP神经网络算法分类模型
- JavaScript 获取当前时间time