JDBC基本操作
JDBC
1、JDBC的简介
JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、新增、更新和删除等操作。
应用程序访问JDBC的图示:

--测试所需的数据库:
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcStudy;
CREATE TABLE `users`(
id INT PRIMARY KEY,
NAME VARCHAR(40),
PASSWORD VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,"zhansan","123456","zs@sina.com","1980-12-04"),
(2,"lisi","123456","lisi@sina.com","1981-12-04"),
(3,"wangwu","123456","wangwu@sina.com","1979-12-04");
此测试所需要用到的所有JAR包:链接:https://pan.baidu.com/s/11XKXch0JFtwPTlakQ0sVcw 提取码:0201
2、第一个JDBC程序
简记口诀:贾琏欲执事(加连预执释) 引入依赖,加载驱动 连接数据库 创建预编译语句 设置参数,执行sql 关闭连接,释放资源。
具体步骤如下:
(1)加载并注册数据库驱动。
(2)通过DriverManager获取数据库连接。
(3)通过Connection对象获取Statement对象。
(4)使用Statement执行SQL语句。
(5)操作ResultSet结果集。
(6)关闭连接,释放资源。
- 加载驱动:
Class.forname("com.mysql.jdbc.Driver"); //固定格式
//设置链接和用户名/密码:
String url = "jdbc:使用的数据库类型://主机地址:端口号/数据库名称? useUnicode=true&characterEncoding=utf8&useSSL=false";
String username = "数据库用户名";
String passwd = "数据库密码";
- 连接数据库:
Connection con = DriverManager.getConnection(url, uername, passwd);
- 创建预编译语句:
Statement statement = con.createStatement();
- 执行sql语句:
String sql = "select * from jdbcstudy";
ResultSet resultset = statement.executeQuery(sql);
//输出结果:
while(resultset.next()){
System.out.println("数据库的数据1:" + resultset.getObject("id"));
}
- 释放资源:
//开启多少个资源就要关闭多少个,先开后关:
resultset.close();
statement.close();
con.close();
2.1 JDBC中对象的解释
DriverManager与Connection
DriverManager类用于加载JDBC驱动并且创建与数据库的连接。
Connection接口代表Java程序和数据库的连接,只有获得该连接对象后,才能访问数据库,并操作数据表。
//DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //不建议使用
//1、加载驱动:(固定格式)
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, passwd);
//Connection 代表数据库:
connection.setAutoCommit();
connection.commit();
connection.rollback();
URL
//设置数据的链接:
String url = "jdbc:使用的数据库类型://主机地址:端口号/数据库名称?参数1&参数2&参数3";
Satement 执行sql对S象
Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。
statement.executeQuery(String sql); //用于查找操作,返回ResultSet
statement.executeUpdate(String sql); //用于增删改操作,返回一个受影响的行数
statement.execute(String sql); //用于增删改查操作
ResultSet 查询结果集:封装了所有查询的结果
ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可将游标移动到下一行。如果下一行没有数据,则返回false。在应用程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。
获得指定的数据类型:
//不知道数据库列类型的时候使用:
resultSet.getObject();
//知道数据库列类型的时候使用:
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
遍历输出查询结果:
resultSet.next(); //移动到下一个数据
resultSet.previous(); //移动到上一个数据
resultSet.beforeFirst(); //移动到最前面
resultSet.afterLast(); //移动到最后面
resultSet.absolute(row); //移动到指定行
2.2 代码实现
提取工具类
//定义一个db.properties文件:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql//localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
passwd=123456
public Jdbc{
//提取到全局作用域:
private static String driver = null;
private static String url = null;
private static String username = null;
private static String passwd = null;
static {
try{
InputStream in = Jdbc.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
uername = properties.getProperty("username");
passwd = properties.getProperty("passwd");
//加载驱动:
Class.forname(driver);
}catch(Exception e){
e.printStackTrace();
}
}
//定义一个连接数据库的方法:
public static Connection getConnection(){
Connection con = DriverManager.getConnection(url,username,passwd);
return con;
}
//定义一个释放资源的方法:
public static void release(Connection con,Statement sta,ResultSet res){
try{
if(con != null){
con.close();
}
}catch(Exception e){
e.printStackTrace();
}
try{
if(sta != null){
sta.close();
}
}catch(Exception e){
e.printStackTrace();
}
try{
if(res != null){
res.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
编写增删改方法
//添加数据:
Connection con = null;
Statement sta = null;
try{
con = jdbc.getConnection();
sta = con.createStatement();
String = sql="insert into users values(4,'xxx','123456','12312312@qq.cm','2021-1-1')";
int i = sta.executeUpdate(sql);
if(i > 0){
System.out.println("添加成功");
}
}catch(SQLException e){
e.printStackTrace();
}finally{
jdbc.release(con,sta,null);
}
//修改数据:
Connection con = null;
Statement sta = null;
try{
con = jdbc.getConnection();
sta = con.createStatement();
String sql ="update users set name='lll' where id=4";
int i = sta.executeUpdate(sql);
if(i > 0){
System.out.println("修改成功");
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,sta,null);
}
//删除数据:
Connection con = null;
Statement sta = null;
try{
con = jdbc.getConnection();
sta = con.createStatement();
String sql = "delete from users where id=4";
int i = sta.executeUpdate(sql);
if(i > 0){
System.out.println("删除成功");
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,sta,null);
}
编写查方法
//查询数据:
Connection con = null;
Statement sta = null;
ResultSet res = null;
try{
con = jdbc.getConnection();
sta = con.createStatement();
String sql = "select * from users where id=1";
res = sta.executeQuery(sql);
while(res.next()){
System.out.println("输出name:" + res.getString("name"));
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,sta,res);
}
2.3 SQL注入问题
sql存在漏洞,会被攻击导致数据泄露。‘or’1=1
public class TestSqlinto {
public static void main(String[] args) {
// login("zhansan","123456");
// login("'or'1=1","123456"); //SQL注入,不安全
login("","'or'1=1");
}
//登陆业务:
public static void login(String username,String passwd){
Connection con = null;
Statement sta = null;
ResultSet res = null;
try {
con = Test02.getCon();
sta = con.createStatement();
//select * from users where name='zhansan' and password='123456';
String sql = "select * from users where NAME='"+username+"' and PASSWORD='"+passwd+"'";
res = sta.executeQuery(sql);
while (res.next()){
System.out.println("输出ID:" + res.getInt("id"));
System.out.println("输出name:" + res.getString("NAME"));
System.out.println("输出password:" + res.getString("PASSWORD"));
System.out.println("输出email:" + res.getString("email"));
System.out.println("输出birthday:" + res.getString("birthday"));
System.out.println("****************************");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
Test02.getReales(con,sta,res);
}
}
}
2.4 PreparedStatement对象
PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。该接口扩展了带有参数SQL语句的执行操作,应用该接口中的SQL语句可以使用占位符“?”来代替其参数,然后通过setXxx()方法为SQL语句的参数赋值。
使用PreparedStatement对象可以解决SQL注入不安全的问题。
- 防止SQL注入的本质,把传递进来的参数当作字符;
- 如果其中存在转义字符,则会自动转义;
public class TestPreparedInto {
public static void main(String[] args) {
// login("zhansan","123456");
login("''or 1=1","123456"); //SQL注入问题被解决
}
public static void login(String username,String password){
Connection con = null;
PreparedStatement pstm = null;
ResultSet res = null;
try {
con = JdbcUtils.getConnection();
String sql = "select * from users where name=? and password=?";
pstm = con.prepareStatement(sql);
pstm.setString(1,username);
pstm.setString(2,password);
res = pstm.executeQuery();
while (res.next()){
System.out.println(res.getString("name"));
System.out.println(res.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(con,pstm,res);
}
}
}
增删改方法:
//添加操作:
public class TestInsert{
Connection con = null;
PreparedStatement pstm = null;
try{
con = jdbc.getConnection();
//与Statement的区别:无createStatement,且需要传入sql值;
//sql语句中可以使用 ? 占位符:
String sql = "insert into users(id,NAME,PASSWORD,email,birthday) values(?,?,?,?,?)";
pstm = con.preparedStatement(sql);
//手动给sql语句中?占位符赋值:(第一个问号的位置,具体值)
pstm.setInt(1,4);
pstm.setString(2,"VXXL");
pstm.setString(3,"123456");
pstm.setString(4,"721321@email.com");
//表中的setDate()方法可以设置日期内容,但参数Date的类型是java.sql.Date,而不是 java.util.Date。
pstm.setDate(5,new java.sql.Date(new Date().getTime()));
//执行:与Statement的区别--->不用传参;
int i = pstm.executeUpdate();
if (i > 0){
System.out.println("添加成功");
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,pstm,null);
}
}
//修改操作:
public class TestUpdate{
Connection con = null;
PreparedStatement = null;
try{
con = jdbc.getConnection();
String sql = "update users set name=? where id=?";
pstm = con.preparedStatement(sql);
pstm.setString(1,"VX");
pstm.setInt(2,4);
int i = pstm.executeUpdate();
if(i > 0){
System.out.println("修改成功");
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,pstm,null);
}
}
//删除操作:
public class TestDelete{
Connection con = null;
PreparedStatement pstm = null;
try{
con = jdbc.getConnection();
String sql = "delete from users where id=?";
pstm = con.preparedStatement(sql);
pstm.setInt(1,4);
int i = pstm.executeUpdate();
if(i > 0){
System.out.println("删除成功");
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,pstm,null);
}
}
查询方法:
public class TestSelect{
Connection con = null;
PreparedStatement pstm = null;
ResultSet res = null;
try{
con = jdbc.getConnection();
String sql = "select * form users where name=? and password=?";
pstm = con.preparedStatement(sql);
pstm.setString(1,"VX");
pstm.setString(2,"123456");
res = pstm.executeQuery();
while(res.next()){
System.out.println(res.getString("name"));
System.out.println(res.getString("password"));
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
jdbc.release(con,pstm,res);
}
}
3、使用IDEA连接数据库
具体步骤:(社区版需要下载插件)



如果连接成功,那么就可以在idea使用数据库操作了。
4、JDBC操作事务
基本操作跟mysql的事务操作一样,只不过java中Connection就相当于SQL。
public class TestTransaction {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pstm = null;
try {
con = JdbcUtils.getConnection();
//关闭事务自动提交:
con.setAutoCommit(false);
//开启事务:java中默认开启事务
String sql1 = "update account set money=money-100 where name='A'";
pstm = con.prepareStatement(sql1);
pstm.executeUpdate(); //提交事务
String sql2 = "update account set money=money+100 where name='B'";
pstm = con.prepareStatement(sql2);
pstm.executeUpdate(); //提交事务
con.commit(); //事务成功执行提交
System.out.println("事务处理成功");
con.setAutoCommit(true);
} catch (SQLException e) {
try {
System.out.println("事务处理失败");
con.rollback(); //事务失败执行回滚
} catch (SQLException ex) {
ex.printStackTrace();
}
}finally {
JdbcUtils.release(con,pstm,null);
}
}
}
5、DBCP-C3P0连接池
实质:编写连接池,实现一个接口DataSource
5.1 DBCP连接
需要的JAR包:commons-dbcp-1.4.jar 和 commons-pool-1.6.jar
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
#!-- 初始化连接 --
initialSize=10
#最大连接数量
maxActive=50
#!-- 最大空闲连接 --
maxIdle=20
#!-- 最小空闲连接 --
minIdle=5
#!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:user 与 password 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
提取工具类:
public class JdbcUtils_DBCP {
private static DataSource dataSource = null;
static {
try {
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(in);
//创建数据源 factory 工厂模式 --> 创建:
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接:
public static Connection getConnection() throws SQLException {
return dataSource.getConnection(); //从数据源中获取连接数据库
}
//释放资源:
public static void release(Connection con, Statement sta, ResultSet res){
try {
if (con != null){
con.close();
}
if (sta != null){
sta.close();
}
if (res != null){
res.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
测试类与前面的操作一样;
5.2 C3P0连接
需要的JAR包:c3p0-0.9.5.5.jar 和 mchange-commons-java-0.2.19.jar
//c3p0数据库的配置文件:
<?xml version=1.0 encoding=UTF-8?>
<c3p0-config>
<!--
c3p0的缺省(默认)配置
如果在代码中ComboPooledDataSource ds=new ComboPooledDataSource();这样写就表示使用的是c3p0的缺省(默认)-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&uesSSL=false&serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquiredIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
<!-- c3p0的缺省(默认)配置
如果在代码中ComboPooledDataSource ds=new ComboPooledDataSource("MySQL");这样写就表示使用的是c3p0的使用的name是MySQL -->
提取工具类:
public class TestC3P0 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pstm = null;
try {
con = JdbcUtils_C3P0.getConnection();
String sql = "insert into users (id,NAME,PASSWORD,email,birthday) values (?,?,?,?,?);";
pstm = con.prepareStatement(sql);
pstm.setInt(1,6);
pstm.setString(2,"VXXLL");
pstm.setString(3,"123456");
pstm.setString(4,"8273682@email.com");
pstm.setDate(5,new java.sql.Date(new Date().getTime()));
int i = pstm.executeUpdate();
if (i > 0){
System.out.println("添加成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
测试类与前面的操作一样;
总结:无论你使用什么数据源,其本质都是一样的,都是实现DataSource接口,都是Connection方法;

浙公网安备 33010602011771号