JDBC
数据库驱动:
我们的程序时通过数据库驱动来和数据库打交道
对于开发人员来说,只需掌握JDBC的接口即可:
第一个JDBC程序
首先需要导入数据库驱动 将jar包拷贝到建立好的lib文件夹下然后对lib文件进行右键鼠标
看到下图就是导入数据库驱动成功
测试代码:
代码语言:javascript复制package JDBC;
import java.sql.*;
public class jdbcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2。链接数据库,用户信息和URL,数据库对象 connection 用DriverManager
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url, username, password);
//3.获得执行的sql的对象statement
Statement statement = connection.createStatement();
//执行
String sql = "SELECT * FROM users";
//4.获得返回的结果集
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id" resultSet.getObject("id"));
System.out.println("name" resultSet.getObject("NAME"));
System.out.println("PASSWORD" resultSet.getObject("PASSWORD"));
System.out.println("EMAIL" resultSet.getObject("EMAIL"));
System.out.println("birthday" resultSet.getObject("birthday"));
}
//5.释放资源
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结: 1.加载驱动 2.连接数据库DriveManager 3.获取执行SQL对象的Statement 4.获取返回的结果集 5.释放连接
对象说明
简单的说这个语句就是执行语句
是一个链表 定位在行
结束程序之后,一定要记得释放资源
Statement对象
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sq|语句, executeUpdate执行完后, 将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
提取工具类的建立:
在src文件目录下创建一个db.properties文件,内容如下所示:
代码语言:javascript复制driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username = root
password = 123456
提取工具类的代码:
代码语言:javascript复制package lesson2.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
// db.properties在src文件目录下
private static String driver =null;
private static String url =null;
private static String username =null;
private static String password =null;
static {
try {
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
//先导入一些属性进来
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//驱动只加载一次
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//释放资源
public static void release(Connection conn, Statement sta, ResultSet res) throws SQLException {
if(res!=null){
res.close();
}
if(sta!=null){
sta.close();
}
if(conn!=null){
conn.close();
}
}
}
程序对数据库进行插入操作:
代码语言:javascript复制package lesson2.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestInsert {
public static void main(String[] args) throws SQLException {
Connection conn = null;
Statement sta = null;
ResultSet res = null;
//数据库连接
conn = JdbcUtils.getConnection();
//获得SQL的执行对象
sta = conn.createStatement();
String sql = "INSERT INTO `users`(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES"
"(4,'黄思远','79123','huangsiyuan@qq.com','2000-11-04');";
//执行
int i = sta.executeUpdate(sql);
if(i>0){
System.out.println("修改成功");
}
JdbcUtils.release(conn,sta,res);
}
}
程序对数据库进行查询操作:
代码语言:javascript复制package lesson2.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
public static void main(String[] args) throws SQLException {
//提升作用域
Connection conn = null;
Statement st = null;
ResultSet res = null;
//连接数据库
try {
conn = JdbcUtils.getConnection();
//得到SQL对象
st = conn.createStatement();
//编写Sql
String sql = "select * from users where id = 1";
res = st.executeQuery(sql);
while (res.next()){
System.out.println(res.getString("NAME"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,res);
}
}
}
程序对数据库进行更新操作:
代码语言:javascript复制package lesson2.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) {
//连接数据库
Connection conn = null;
Statement st = null;
ResultSet res = null;
try {
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "UPDATE users SET email = '123456@qq.com',birthday ='1994-12-15' WHERE id = 1";
int i = st.executeUpdate(sql);
if(i > 0){
System.out.println("更新成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
SQL注入
因为这里的statement是不安全的 sql存在漏洞,会被攻击导致数据泄露 SQL会被拼接 or,通过巧妙的技巧来拼接字符串,造成SQL短路,从而获取数据库数据
代码语言:javascript复制package lesson2.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
public static void main(String[] args) throws SQLException {
//SQL注入
login("' or '1=1","' or '1=1");
}
public static void login(String name,String password) throws SQLException {
Connection conn = null;
Statement sta = null;
ResultSet res = null;
//连接数据库
try {
conn = JdbcUtils.getConnection();
//创建sql对象
sta = conn.createStatement();
String sql = "select * from users where `NAME`='" name "' AND `PASSWORD`='" password "'" ;
**加粗样式** res = sta.executeQuery(sql);
while(res.next()){
System.out.println(res.getString("NAME"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,sta,res);
}
}
}
PreparedStatement对象
PreperedStatement是Statement的子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。
PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
java程序对数据库进行查询:
代码语言:javascript复制package lesson03;
import jdk.nashorn.internal.scripts.JD;
import lesson2.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestPSelect {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//创建对象
String sql = "select * from users where id = ?";
st = conn.prepareStatement(sql); //预编译
st.setInt(1,1); //手动赋值
//执行
rs = st.executeQuery();
while (rs.next()){
System.out.println(rs.getString("NAME"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
java程序对数据库进行代码更新:
代码语言:javascript复制package lesson03;
import lesson2.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestPUpdate {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet re = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into users(id,`NAME`) values(?,?)";
st = conn.prepareStatement(sql);
//开始赋值
st.setInt(1,6);
st.setString(2,"狗哥");
//开始执行
int i = st.executeUpdate();
if(i > 0){
System.out.println("更新成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
使用IDEA连接数据库
第一步:
第二步:
在配置数据库的时候,可能会出现如下的问题: 错误:[2020-08-17 08:52:48] Server returns invalid timezone. Need to set ‘serverTimezone’ property.
很显然是时区问题导致的,所以我们在连接的URL后面添加 `
?serverTimezone=GMT+8
`设定mysql的时区为东八区点击Apply应用就好了!
第三步:
第四步:更新数据 点击这个db
第六步:写SQL
事物
要么都成功,要么都失败 ACID原则:
原子性:要么都成功,要么都失败 隔离性:多个线程互补干扰 持久性:一旦提交就不可逆,已经提交到数据库了
隔离性产生的问题: 脏读:一个事物读取了另一个没有提交的事物 不可重复脏读:在同一个事物中,重复读取表中的数据,表也发生了改变 虚读:在一个事物内,读取到了别人插入的数据,导致前后读出来的结果不一致
代码实现: 1.开启事物 2.提交事物
代码语言:javascript复制package lesson04;
import lesson2.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestTransation {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
//连接数据库
try {
conn = JdbcUtils.getConnection();
//开启事物,就是关闭自动提交会自动的开始事物
conn.setAutoCommit(false);
String sql1 = "update account set money = money - 100 where name = 'A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update account set money = money 100 where name = 'B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
conn.commit();//业务完毕,提交事物
System.out.println("成功");
} catch (SQLException throwables) {
//如果失败,就默认回滚
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}
}
}
数据库连接池
数据库连接–执行完毕–释放
连接–释放 十分浪费资源
池化技术: 准备一些预先的资源,过来就连接预先准备好的
常用连接数 100
最少连接数:100
最大连接数 : 120 业务最高承载上限
排队等待,
等待超时:100ms
编写连接池,实现一个接口 DateSource
提取工具类:
代码语言:javascript复制dataSource = BasicDataSourceFactory.createDataSource(properties);
package lesson05.utils;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils_dbcp {
private static DataSource dataSource = null;
static {
try {
InputStream in = JdbcUtils_dbcp.class.getClassLoader().getResourceAsStream("dbcp.properties");
Properties properties = new Properties();
properties.load(in);
//创建数据源 工厂模式---->创建
try {
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//从数据源中获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放资源
public static void release(Connection conn, Statement sta, ResultSet res) throws SQLException {
if(res!=null){
res.close();
}
if(sta!=null){
sta.close();
}
if(conn!=null){
conn.close();
}
}
}
代码语言:javascript复制package lesson05.utils;
import lesson2.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDBCP {
public static void main(String[] args) {
//提升作用域
Connection conn = null;
Statement st = null;
ResultSet res = null;
//连接数据库
try {
//从连接池中获取一个连接
conn = JdbcUtils_dbcp.getConnection();
//得到SQL对象
st = conn.createStatement();
//编写Sql
String sql = "select * from users where id = 1";
res = st.executeQuery(sql);
while (res.next()){
System.out.println(res.getString("NAME"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
JdbcUtils_dbcp.release(conn,st,res);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}