功能:
本人使用的是jdk10和mysql-connector-java-5.1.45-bin.jar。
步骤:
释放资源
// 2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3. 获取连接对象Collection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "nrblwbb7");
// 4. 定义sql
String sql = "UPDATE STUDENT SET AGE = 23 WHERE NAME = '王智'";
// 5. 获取执行sql语句的对象 Statement
Statement statement = conn.createStatement();
// 6. 执行sql,接受返回结果(ResultSet)
int result = statement.executeUpdate(sql);
// 7. 处理结果
System.out.println(result);
// 8. 释放资源
statement.close();
conn.close();
ResultSet rs = null;
使用Connection对象来管理事务
测试:
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
// 1.创建sql,转账的sql
String sql1 = "UPDATE ACCOUNT SET BALANCE = BALANCE - ? WHERE ID = ?";
String sql2 = "UPDATE ACCOUNT SET BALANCE = BALANCE + ? WHERE ID = ?";
// 2.获取连接对象
conn = JDBCUtils.getConn();
// 开启事务
conn.setAutoCommit(false);
// 3.获取执行sql对象,进行预编译
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
// 4.替换占位符
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
// 5.执行sql
pstmt1.executeUpdate();
// int i = 3 / 0;
pstmt2.executeUpdate();
// 提交事务
conn.commit();
} catch (Exception e) {
if(conn != null) {
try {
// 事务回滚
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
ROLLBACK
功能:
注册驱动:告诉程序该使用哪一个数据库驱动jar
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
获取数据库连接
- 所有的数据库连接池都需要实现DataSource,当使用数据库连接池时,我们便不再需要使用DriverManger获取数据库连接
功能:
- java.sql.DriverManager
//执行SQL语句
功能:
举个简单例子:
@Test
public void selectDemo(){
try {
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.创建sql语句
String sql = "select * from account";
try(
// 3.获取连接对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"root");
// 4.获取执行sql语句对象
Statement stmt = conn.createStatement()
){
// 5.执行sql
ResultSet rs = stmt.executeQuery(sql);
// 6.处理结果集
while(rs.next()){
// 获取id
int id = rs.getInt("id");
// 获取姓名
String name = rs.getString("name");
// 获取账户余额
double balance = rs.getDouble("balance");
// 正确的处理应该是封装为对象,进行处理,这就简单展示下
System.out.println("id = " + id + ", name = " + name + ", balance = " + balance);
}
} catch (SQLException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
2.操作数据库
src下db.properties的信息:
# 驱动
driver=com.mysql.jdbc.Driver
# url
url=jdbc:mysql://127.0.0.1:3306/db3?useSSL=true
# 用户
username=root
# 密码
password=root
封装的工具类如下:
public class JDBCUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
try {
// 读取配置文件
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties pro = new Properties();
pro.load(inputStream);
// 静态变量赋值
driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
// 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接对象
* @return 返回连接对象
*/
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
/**
* 关闭资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//控制光标下移一行
功能:
插入举例:
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useSSL=true", "root", "nrblwbb7");
// 3. 创建sql
String sql = "INSERT INTO ACCOUNT VALUES (NULL,'网址',2000)";
// 4. 获取执行sql对象
stmt = conn.createStatement();
// 5. 执行sql
int count = stmt.executeUpdate(sql);
// 6. 处理结果
System.out.println("影响的行数为:" + count);
if(count > 0){
System.out.println("插入成功");
}else{
System.out.println("操作失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7. 释放资源
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
修改举例:
public static void main(String[] args) {
/**
* 由于Connection和Statement实现了AutoCloseable接口,所以可以使用自动关闭
*/
try(
// 2.获取Connection对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"nrblwbb7") ;
// 3. 获取Statement对象
Statement stmt = conn.createStatement()
){
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 4. 创建sql
String sql = "UPDATE ACCOUNT SET BALANCE = 1500 WHERE NAME = '网址'";
// 5. 执行sql
int count = stmt.executeUpdate(sql);
// 6. 处理结果
System.out.println(count);
if(count > 0){
System.out.println("修改成功");
}else{
System.out.println("操作失败或者记录未更改");
}
// 7. 关闭连接,由于try..with..resource会自动关闭,所以无须担心
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
删除举例:
public static void main(String[] args) {
/**
* 由于Connection和Statement实现了AutoCloseable接口,所以可以使用自动关闭
*/
try(
// 2.获取Connection对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3?useSSL=true",
"root",
"nrblwbb7") ;
// 3. 获取Statement对象
Statement stmt = conn.createStatement()
){
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 4. 创建sql
String sql = "DELETE FROM ACCOUNT WHERE NAME = '网址'";
// 5. 执行sql
int count = stmt.executeUpdate(sql);
// 6. 处理结果
System.out.println(count);
if(count > 0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
// 7. 关闭连接,由于try..with..resource会自动关闭,所以无须担心
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
- Connection getConnection()
而我们传递的参数时通过拼接字符串的形式添加进SQL语句
注意:如果查询的SQL使用了别名,则列名以别名为准。
- JDBC就是Java中连接数据库方式
转换为一个类似于Java中方法的东西,而我们的那些填充的占位符,会以方法的参数的形式发送给MySQL
- 在ResultSet有很多getXxx(int),比如getString(),getInt(),getByte()。
1.大文本数据
// TODO Auto-generated catch block
try{
#开启事务
- 问题:
1.导入数据库驱动的jar包
4.通过DriverManager来获取数据库连接
> 数据库连接池的常见的属性:
}
- 设置事务是否自动提交,默认是自动提交
conn.rollback();
原子性(atomicity)
int id = rs.getInt("id");
列数是从1开始的。
使用完的数据库连接,也不是直接销毁,而是要放回到连接池。
- DBCP依赖于commons-pool
3.回滚事务
比如:我们要获取id的值
2.JDBC
"SELECT * FROM t_user WHERE username='a' OR 'a'='a' AND password='a' OR 'a'='a'"
getString("name")
当需要读取全部数据时,用while
}
rs.close();
Statement stmt = null;
- password
1) SQL注入
6) 数据库连接池
Class.forName(driverClass)
- 大数据主要分两种:
- int executeUpdate(String sql)
if(rs.next()){
Class.forName("com.mysql.jdbc.Driver");
void setAutoCommit(boolean autoCommit) throws SQLException;
int指的是读取数据的列数。
//创建一个Connection
而是使用DataSource。
最大等待时间:当数据库连接池饱和以后,等待获取数据库连接的时间
commons-pool-1.5.5.jar
ComboPooledDataSource
try {
Statement stat = conn.createStatement();
}finally{
- 数据库驱动的管理器,负责加载数据库的驱动获取数据库连接
1.在用户输入时进行验证,验证用户名中是否包含特殊字符 ' " 等等
e.printStackTrace();
在关 Statement
e.printStackTrace();
> java.sql.PreparedStatement --> 预编译的Statement
- 核心类:
- 这个方法用来执行SQL语句,这个方法会将批处理中所有SQL语句执行
> 查询操作和修改的主要不同的是,查询使用executeQuery(),
int[] executeBatch()
} catch (SQLException E) {
- 创建一个Statement对象,通过Statement对象来执行SQL语句
要么同时成功,要么全都失败。
commons-dbcp-1.4.jar
} catch (SQLException e) {
http://www.cnblogs.com/libingbin/
2)获取数据库连接
//操作成功,提交事务
- 设置事务手动提交
> PreparedStatement是Statement的子接口,使用方式和Statement类似,但是它在Statement做了一些扩展。
- 示例代码:
- 事务控制的格式:
这个代码会将数据库驱动注册进DriverManager中。
- C3P0使用的是XML作为配置文件
- 核心类:
DataSource就相当于池子,我们的数据库连接都是从DataSource中获取的,
即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
}
- mysql中的事务控制
再去调用close()数据库连接将不会真的关闭,而是要放回到数据库连接池中,供其他线程使用。
2.大的字节数据
//获取Connection
stmt.close();
隔离性(isolation)
> 数据库连接池就是存放数据库连接(Connection)的集合
- 执行查询的SQL语句,并返回一个结果集
int count = stat.executeUpdate(sql);
使用PreparedStatement,执行一次以后,会对SQL语句进行缓存,下次再次执行时效率更高。
4.数据库驱动全类名 driverClass
- Statement和PreparedStatement都支持批处理操作,这里我们只需要掌握PreparedStatement的批处理方式:
> 当我们只需要读取一个数据时,用if。
//回滚事务
//执行查询
- boolean execute(String sql)
这样即使传递在奇怪的参数,也不能改变SQL语义,所以它有效的避免了SQL注入的问题。
> 我们获取一个数据库连接是一个相对很麻烦的过程,
//创建一个SQL语句
- 操作事务的基本步骤:
}
String sql = "SELECT id, name sname, age FROM t_stu WHERE id=2";
- 注意:
} catch (SQLException e1) {
//定义三个变量
//获取id,name,age
- 静态代码块会在类被加载进虚拟机时就会执行,也就是当我们调用 Class.forName("com.mysql.jdbc.Driver");
这样就对我们的网站带来很大的安全隐患
- 查询到的数据的结果集,我们通过JDBC查询数据库获得的数据,都封装在ResultSet中
- url
void addBatch()
}
- Class.forName() 主要是将一个类加载进的虚拟机。
最大空闲连接数:数据库连接池最大闲置连接数,当闲置连接数满了以后,将不会有其他连接进入池
而且,这行代码不写也好使,这是为什么呢?
//如果当前行有数据,则读取
conn.commit();
- 通过观察mysql的Driver的源码,发现类中有一个静态代码块:
> 代码的规范:
- 开启事务以后再去操作数据库,所有操作将不会直接提交到数据库中
//创建一个SQL执行器
- boolean next()
从后往前关:
- 当我们通过数据库连接池获取数据库连接以后,我们所获取到数据库连接已经不是我们熟悉的那个Connection
> 通过这种特殊的参数,导致我们SQL语句的语义完全改变,这样即使用户名和密码不正确也可以登录
- 事务的特性(ACID):
4)数据的查询
c3p0-0.9.1.2.jar
- mysql默认批处理是关闭的,所以我们还需要去打开mysql的批处理:
> 获取PreparedStatement是通过Connection的prepareStatement()的方法获取的,这个方法需要传一个SQL语句,
在my.ini文件中添加如下配置
1.开启事务
- 开启事务以后,我们只后的所有操作将都会在同一个事务当中
> 这种形式如果正常用户的访问,问题不大,但是一旦出现恶意的用户,
if(stmt != null){
- 我们可以通过JDBC来执行SQL语句。
mysql-connector-java-5.1.37-bin.jar
- 使用c3p0需要导入一个jar包:
如果我们获取一个数据库连接,使用一次以后就给它关闭了
5) 事务(Transaction)
2.提交事务
try{
如果程序中有多个DataSource的实例,那么我们说你还不如不用数据库连接池。
- 注意:我们在同一个事务中使用的数据库连接(Connection)必须是同一个。
java.sql.DriverManager.registerDriver(new Driver());
}
- java.sql.Statement
他如果传递了这样一组参数 用户名 : a' OR 'a'='a 密码:a' OR 'a'='a
2) PreparedStatement
- 方法:
}catch(Exception e){
- Connection、Statement、ResultSet,这些资源都是需要和数据建立连接的
以后,该静态代码块会立即执行。
//对数据库进行操作
static Connection getConnection(String url, String user, String password)
本文由美高梅官方网站发布于数据统计,转载请注明出处:Java之JDBC