学习地址

https://www.bilibili.com/video/av63345438

JDBC概念
JDBC(Java DataBase Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去分别实现这套接口,提供数据库驱动 jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动 jar包中的实现类。

JDBC执行步骤
1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
—-1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
—-2.右键–>Add As Library
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
5. 获取执行sql语句的对象 Statement
6. 执行sql,接受返回结果
7. 处理结果
8. 释放资源
使用eclipse创建javaweb使用jdbc,参考以下

https://blog.csdn.net/alexshi5/article/details/78956378

<% 
   // ①注册数据库驱动
   Class.forName("com.mysql.jdbc.Driver");
   //String url1 = "jdbc:mysql://localhost:3306/(你的数据库名)";
   String url1 = "jdbc:mysql://localhost:3306/tubu_dangqian";
   String url2 = "?user=root&password=root";
   String url3 = "&useUnicode=true&characterEncoding=UTF-8";
   String url = url1 + url2 + url3;
   // ②获取数据库链接
   Connection con = DriverManager.getConnection(url);
   // ③的定义sql语句
   String sql = "Insert into tb_sms (event,mobile) values(?,?)";
   // ④获取执行sql语句的对象 Statement
   PreparedStatement pstmt = con.prepareStatement(sql);
   pstmt.setString(1,"register");
   pstmt.setLong(2,17625353140L);
   // ⑤执行sql,接受返回结果
   int n = pstmt.executeUpdate();
   if(n==1){%> 数据插入操作成功!<br> <% }
   else{%> 数据插入操作失败!<br> <% }
   if(pstmt!=null){pstmt.close();}
   // ⑥释放资源
   if(con!=null){con.close();}
 %>

详解各个对象
1.DriverManager:驱动管理对象
功能:
①注册驱动:告诉程序该使用哪一个数据库驱动(mysql5之后的jar包可以省略注册驱动)

    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

②获取数据库链接
数据库链接jdbc:mysql://localhost:3306/tubu_dangqian?user=root&password=root&useUnicode=true&characterEncoding=UTF-8
本地数据库链接可以省略数据库地址和端口:jdbc:mysql:///tubu_dangqian?user=root&password=root&useUnicode=true&characterEncoding=UTF-8
2.Connection对象
1.功能:
1.获取执行sql的对象
*Statement createStatement()
*PreparedStatement prepareStatement(String sql)
2.管理事务
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为 false,即开启事务
提交事务:commit()
回滚:rollback()
3.Statement:执行sql的对象
1.执行sql

  • ①.boolean execute(String sql):可以执行任意的 sql(了解)
  • ②.int executeUpdate(String sql):执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句(DDL语句不返回影响的行数)
    返回值:影响的行数,可以通过这个影响的行数判读DML语句是否执行成功,如果返回值 > 0,则执行成功,反之,失败。
  • ③.ResultSet executeQuery(String sql):执行DQL(select)语句
package com.jdbc;
import java.sql.*;
 
public class updateUser {
 
	public static void toDo() {
		Statement stmt = null;
		Connection con = null;
		try {
			// ① 注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// ② 获取数据库Connection对象
			con = DriverManager.getConnection("jdbc:mysql://localhost:3306/tubu_dangqian?user=root&password=root");
			// ③ 定义sql语句
			//添加 String sql = "insert into tb_sms values(null,'register','17625353140')";
			//更新 String sql = "update tb_sms set event = 'login111' where id = 11096";
			String sql = "delete from  tb_sms where id = 11096";
			// ④ 获取执行sql的对象 Statement
			stmt = con.createStatement();
			// ⑤ 执行sql
			int count = stmt.executeUpdate(sql);
			// ⑥ 处理结果
			if(count>0) {
				System.out.println("操作成功");
			}else {
				System.out.println("操作失败");
			}
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally {
            // ⑦ 释放资源
            // 避免空指针异常
			if(stmt!=null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(con!=null) {
				try {
					con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

4.ResultSet:结果集对象,封装查询结果
1.基本使用
boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回 false,否则返回 true
getXxx(参数):获取数据
Xxx:代表数据类型 如 int getInt(), String getString()
参数:
int:代表列的编号,从1开始 如 getString(1)
String:代表列的名称 如 getDouble(“balance”)
使用步骤:
游标向下移动一行
使用循环,用 next 方法判断是否有数据
获取数据

package com.jdbc;
import java.sql.*;
 
public class selectDemo {
	public static void toDo() {
		Connection con = null;
		Statement stmt = null;
		ResultSet result = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			con = DriverManager.getConnection("jdbc:mysql:///tubu_dangqian?user=root&password=root");
			String sql = "select * from tb_sms";
			stmt = con.createStatement();
			result = stmt.executeQuery(sql);
			//处理结果  默认游标在最上边
			while(result.next()) {
				System.out.println(result.getInt(1));
				System.out.println(result.getString("event"));
				System.out.println(result.getLong(3));
			}
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally {
            // ⑦ 释放资源
            // 避免空指针异常
			if(result!=null) {
				try {
					result.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(stmt!=null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(con!=null) {
				try {
					con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

+++++++++++++++++++++++++++++++++
结果集封装成对象练习
User.java

package com.jdbc;
 
public class User {
	private int id;
	private String username;
 
	public String toString() {
		return "id:"+this.getId()+"username:"+this.getUsername();
	}
 
	public int getId() {
		return id;
	}
 
	public void setId(int id) {
		this.id = id;
	}
 
	public String getUsername() {
		return username;
	}
 
	public void setUsername(String username) {
		this.username = username;
	}
 
}

UserDao.java

package com.jdbc;
import java.util.ArrayList;
import java.util.List;
 
import com.jdbc.User;
import java.sql.*;
 
public class UserDao {
 
	public List<User> FindAll(){
		List<User> list = new ArrayList<User>();
		Connection con = null;
		Statement stmt = null;
		ResultSet result = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/user?user=root&password=root";
			con = DriverManager.getConnection(url);
			String sql = "select * from users";
			stmt = con.createStatement();
			result = stmt.executeQuery(sql);
			while(result.next()) {
				int id = result.getInt(1);
				String userName = result.getString("user_name");
				User user = new User();
				user.setId(id);
				user.setUsername(userName);
				list.add(user);
			}
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally{
			if(result!=null) {
				try {
					result.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			if(stmt!=null) {
				try {
					stmt.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			if(con!=null) {
				try {
					con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	return list;
	}
 
	public void toGo() {
		System.out.println(this.FindAll());
	}
}

+++++++++++++++++++++++++++++++++
抽取JDBC工具类 : JDBCUtils
1. 注册驱动也抽取
2. 抽取一个方法获取连接对象
* 需求:不想传递参数(麻烦),还得保证工具类的通用性。
* 解决:配置文件
jdbc.properties
url=
user=
password=
3. 抽取一个方法释放资源

jdbc.properties文件

user=root
password=root
url=jdbc:mysql://localhost:3306/user
driver=com.mysql.jdbc.Driver

JDBCUtils.java

package utils;
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
 
public class JDBCUtils {
 
	public static String driver;
	public static String url;
	public static String user;
	public static String password;
 
	/**
	 * 文件的读取,只需要读取一次即可拿到这些值,使用静态代码块
	 */
	static {
		try {
			Properties properties = new Properties();
 
			// 获取src路径下的文件的方式 ClassLoader类加载器
			ClassLoader classLoader = JDBCUtils.class.getClassLoader();
			URL res = classLoader.getResource("jdbc.properties");
			String path = res.getPath();
			properties.load(new FileReader(path));
			// 加载文件路径 properties.load(new
			// FileReader("C:\\Users\\Administrator\\eclipse-workspace\\javademo\\src\\jdbc.properties"));
			driver = properties.getProperty("driver");
			user = properties.getProperty("user");
			password = properties.getProperty("password");
			url = properties.getProperty("url") + "?user=" + user + "&password=" + password;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
 
	/**
	 * 获取数据库链接
	 */
	public static Connection getConnnection() {
 
		Connection con = null;
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url);
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
 
		return con;
	}
 
	/*
	 * 释放资源
	 */
	public static void closeResourse(Statement stmt, Connection connection) {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

UserDao2.java

package com.jdbc;
import java.util.ArrayList;
import java.util.List;
 
import com.jdbc.User;
import java.sql.*;
import utils.JDBCUtils;
 
public class UserDao2 {
 
	public List<User> FindAll(){
		List<User> list = new ArrayList<User>();
		Connection con = null;
		Statement stmt = null;
		ResultSet result = null;
		try {
			con = JDBCUtils.getConnnection();
			String sql = "select * from users";
			stmt = con.createStatement();
			result = stmt.executeQuery(sql);
			while(result.next()) {
				int id = result.getInt(1);
				String userName = result.getString("user_name");
				User user = new User();
				user.setId(id);
				user.setUsername(userName);
				list.add(user);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(result!=null) {
				try {
					result.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			JDBCUtils.closeResourse(stmt, con);
 
		}
	return list;
	}
 
	public void toGo() {
		System.out.println(this.FindAll());
	}
}

5. PreparedStatement:执行sql的对象
1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
          1. 输入用户随便,输入密码:a’ or ‘a’ = ‘a
          2. sql:select * from user where username = ‘fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’

2. 解决sql注入问题:使用PreparedStatement对象来解决
3. 预编译的SQL:参数使用?作为占位符
4. 步骤:
          1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
          2. 注册驱动
          3. 获取数据库连接对象 Connection
          4. 定义sql
          * 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
          5. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
          6. 给?赋值:
          方法: setXxx(参数1,参数2)
          * 参数1:?的位置编号 从1 开始
          * 参数2:?的值
          7. 执行sql,接受返回结果,不需要传递sql语句
          8. 处理结果
          9. 释放资源

5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
          1. 可以防止SQL注入
          2. 效率更高
++++++++++++++
JDBC控制事务:
1. 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
2. 操作:
  1. 开启事务
  2. 提交事务
  3. 回滚事务
3. 使用Connection对象来管理事务
  * 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
      * 在执行sql之前开启事务
  * 提交事务:commit()
      * 当所有sql都执行完提交事务
  * 回滚事务:rollback()
      * 在catch中回滚事务
事务练习

package com.jdbc;
import utils.JDBCUtils;
import java.sql.*;
 
public class jdbcDemo2 {
	public static void transfer() {
		Connection con = JDBCUtils.getConnnection();
		PreparedStatement stmtMinus = null;
		PreparedStatement stmtPlus = null;
		try {
			con.setAutoCommit(false);
			String sql1 = "update users set balance = balance - 5 where id = ?";
			stmtMinus = con.prepareStatement(sql1);
			String sql2 = "update users set balance = balance + 5 where id = ?";
			stmtPlus = con.prepareStatement(sql2);
			stmtMinus.setInt(1,1);
			stmtPlus.setInt(1, 2);
			stmtMinus.execute();
			stmtPlus.execute();
			con.commit();
 
		} catch (SQLException e) {
			System.out.print(e.getMessage());
			try {
				if(con!=null) {
					con.rollback();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			JDBCUtils.closeResourse(stmtMinus, con);
			JDBCUtils.closeResourse(stmtPlus, null);
		}
	}
}

数据库连接池
1.概念:
  其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器会申请有一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完,会将连接对象归还给容器。

2.好处:
  节约资源
  用户访问高效

3. 实现:
  1. 标准接口:DataSource javax.sql包下的
    1. 方法:
      * 获取连接:getConnection()
      * 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接

  2. 一般我们不去实现它,有数据库厂商来实现
    1. C3P0:数据库连接池技术
    2. Druid:数据库连接池实现技术,由阿里巴巴提供的

Configuration files are normally looked up under standard names (c3p0.properties or c3p0-config.xml) at the top level of an application’s classpath, but the XML configuration can be placed anywhere in an application’s file system or classpath, if the system property com.mchange.v2.c3p0.cfg.xml is set.
4.C3P0
1 右键项目-Properties-Java Build Path-Libraries-Add External JARs-导入c3p0-0.9.5.2.jar和mchange-commons-java-0.2.11.jar
2 导入c3p0-config.xml
注意:通常情况下,java web项目会自动将WEB-INF项目下的lib添加到类路径下的,tomcat发布的部署包时也是会从lib目录下加载的。
但是开发阶段是会出现Eclipse没有自动将lib下的jar添加到类路径下,这是需要手动build path添加到类路径下的。
具体原因不明,但是作为一种经验可以记录下,如果发布时找不到加载类,就手动把lib下jar添加到build path下面。可以肯定的是项目部署到tomcat里面是不会出现这种情况的,只是在Eclipse开发环境中会出现。
使用连接池示例

package com.jdbc;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class C3P0Demo {
 
	public static void toGo() {
 
		DataSource ds = new ComboPooledDataSource("mysql");
		Connection con = null;
		try {
			con = ds.getConnection();
			String sql = "select * from users";
			Statement stmt = con.createStatement();
			ResultSet res = stmt.executeQuery(sql);
			while(res.next()) {
				System.out.println(res.getInt(1)+res.getString(2));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		System.out.println(con);
	}
}

src下的c3p0-config.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <named-config name="mysql">
        <!-- 配置数据库用户名 -->
        <property name="user">root</property>
        <!-- 配置数据库密码 -->
        <property name="password">root</property>
        <!-- 配置数据库链接地址 -->
        <property name="jdbcUrl"><![CDATA[jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=UTF-8]]></property>
        <!-- 配置数据库驱动 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!-- 数据库连接池一次性向数据库要多少个连接对象 -->
        <property name="acquireIncrement">20</property>
        <!-- 初始化连接数 -->
        <property name="initialPoolSize">10</property>
        <!-- 最小连接数 -->
        <property name="minPoolSize">5</property>
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize">30</property>
        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
        <property name="maxStatements">0</property>
        <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
        <property name="maxStatementsPerConnection">0</property>
        <!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default:3 -->
        <property name="numHelperThreads">3</property>
        <!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
        <property name="propertyCycle">3</property>
        <!-- 获取连接超时设置 默认是一直等待单位毫秒 -->
        <property name="checkoutTimeout">1000</property>
        <!--每多少秒检查所有连接池中的空闲连接。Default: 0 -->
        <property name="idleConnectionTestPeriod">3</property>
        <!--最大空闲时间,多少秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime">10</property>
        <!--配置连接的生存时间,超过这个时间的连接将由连接池自动断开丢弃掉。当然正在使用的连接不会马上断开,而是等待它close再断开。配置为0的时候则不会对连接的生存时间进行限制。 -->
        <property name="maxIdleTimeExcessConnections">5</property>
        <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
        <property name="acquireRetryDelay">1000</property>
        <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。Default: null -->
        <property name="automaticTestTable">Test</property>
        <!-- 获取connnection时测试是否有效 -->
        <property name="testConnectionOnCheckin">true</property>
    </named-config>
</c3p0-config>

5.Druid:Alibaba提供的数据库连接池技术
使用步骤:

导入jar包:
定义配置文件:
是Properties格式的
可以为任意的名称,放在任意的目录下
加载配置文件 Properties文件
获取连接池对象:使用工厂类获取DruidDataSourceFactory.createDataSource(pro);
获取连接,连接池对象.getConnection();
++++++++++++++++++++++
druid.properties文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/user
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
package com.jdbc;
 
import java.io.InputStream;
import java.util.Properties;
import javax.sql.DataSource;
import java.sql.*;
 
import com.alibaba.druid.pool.DruidDataSourceFactory;
 
public class DruidDemo {
	public static void toDo() throws Exception {
		Properties pro = new Properties();
		// 配置文件
		InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
		pro.load(is);
		DataSource ds = DruidDataSourceFactory.createDataSource(pro);
			Connection con = ds.getConnection();
			System.out.println(con);
	}
}

JDBCUtils druid工具类
一般还是自己定义一个工具类,用来加载配置文件,初始化连接池,释放资源等

定义一个类JDBCUtils
在一个静态代码块里编写加载配置文件
方法:
获取连接的方法:通过数据库连接池获取连接
释放资源的方法
获取连接池的方法
+++++++++++++++++++++++++++++++++++++++
DRUIDJDBCUtils.java文件 封装数据库链接池工具类

package utils;
 
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
 
import javax.sql.DataSource;
 
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.jdbc.DruidDemo;
 
public class DRUIDJDBCUtils {
 
	private static DataSource ds;
 
	/**
	 * 获取链接
	 */
	static {
		try {
			Properties pro = new Properties();
			InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
			pro.load(is);
			ds = DruidDataSourceFactory.createDataSource(pro);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
	/**
	 * 获取数据库链接资源
	 */
	public static Connection getConnection() throws SQLException {
		return ds.getConnection();
	}
 
	/**
	 * 释放资源
	 */
	public static void close(ResultSet res,Statement stmt, Connection con) {
		if(res!=null) {
			try {
				res.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (con != null) {
			try {
				con.close();  // 归还链接资源
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
 
}

使用工具类

package com.jdbc;
 
import java.sql.*;
 
import utils.DRUIDJDBCUtils;
 
public class jdbcDemo3 {
 
	public static void toGo() {
		Statement stmt = null;
		Connection con = null;
		ResultSet res = null;
		try {
			con = DRUIDJDBCUtils.getConnection();
			String sql = "select * from users";
			stmt = con.createStatement();
			res = stmt.executeQuery(sql);
			while (res.next()) {
				System.out.println(res.getInt(1));
				System.out.println(res.getString(2));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			DRUIDJDBCUtils.close(res,stmt, con);
		}
 
	}
 
}

+++++++++++++++++++++++++++++++++++++++

发表评论

邮箱地址不会被公开。 必填项已用*标注