Day10
1. JDBC(java连接数据库)
-
是一条规范,一套接口,所有数据库厂家都要对JDBC提供的接口进行实现
-
通过java连接数据库时,需要关心:
- 如何获取数据库对象
- 如何操作数据库
- 如何提交数据库事务
-
JDBC编程六大步骤:
- ==1、==加载数据库驱动
- 法一:此法效率不高,每次都要new一个新的对象
DriverManager.registerDriver(new Driver());
- 法二:采用类加载方式(此方法可提高程序性能)
Class.forName("全限定类名");
//可以使得类加载- 全限定类名:类所在包名+类名,例如:com.mysql.cj.jdbc.Driver
- 法一:此法效率不高,每次都要new一个新的对象
- ==2、==获取数据库连接对象
Connection conn = DriverManager.getConnection(String url, String user, String password)
- url:连接数据库的地址——❤
“jdbc:mysql://localhost:3306/数据库名称(zj1)”
- ❤jdbc:mysql://——一个协议,例如http://
- ❤localhost——本地ip地址127.0.0.1
- ❤3306——端口号,每个端口号监听一个服务,3306监听的就是sql服务
- user:数据库用户名(root)
- password:登录数据库密码(123)
- url:连接数据库的地址——❤
- ==3、==通过数据库连接对象获取数据库操作对象(用于执行增删改查的对象)
Statement s=connection.createStatement();
//sql增删改查语句写在这里面
- ==4、==写sql语句,执行sql
- ==DML(增删改)==调用
statement.executeUpdate();
来执行sql语句 - ==DQL(查)==调用
statement.executeQuery();
来执行sql语句
- ==DML(增删改)==调用
- ==5、==如果是查询语句,需要获取结果集,处理数据/如果是增删改语句,需要获取影响记录条数据,处理数据
- ==6、==关闭数据库资源
- ==1、==加载数据库驱动
1.1 DML(增删改)
❤statement.executeUpdate(sql);
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo02 {
public static void main(String[] args) {
Connection connection =null;
Statement statement =null;
//连接数据库
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zj1" +
"?serverTimezone=GMT&characterEncoding=utf8", "root", "123");
//3、获取数据库操作对象
statement = connection.createStatement();
//4、定义sql
String sql = "update user set uname='gay',pword='456' where id=1";
//4、执行sql
int num = statement.executeUpdate(sql); //返回的是数据库中受影响记录条数
//5、校验是否操作成功
System.out.println(num == 1 ? "修改成功" : "修改失败");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{ //无论如何都会执行,避免资源浪费
//6、关闭数据库资源
try {
//要做一下判空,否则会报空指针异常,体现程序严谨
if(statement!=null){
statement.close(); //关闭资源statement
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close(); //关闭资源connection
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.2 DQL(查)
❤statement.executeQuery(sql);
需求1:
1、在数据库创建user表,字段:id,uname,pword
2、控制台输入用户名,密码,用sql来判断是否有此用户
/**
法一:先遍历sql中的数据,再与输入值比较
*/
import java.sql.*;
import java.util.Scanner;
public class JDBCDemo02 {
public static void main(String[] args) {
Connection connection =null;
Statement statement =null;
ResultSet result=null;
Scanner sc1=new Scanner(System.in);
System.out.print("请输入用户名:");
String u=sc1.next();
Scanner sc2=new Scanner(System.in);
System.out.print("请输入密码:");
String p=sc2.next();
//连接数据库
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zj1" +
"?serverTimezone=GMT&characterEncoding=utf8", "root", "123");
//3、获取数据库操作对象
statement = connection.createStatement();
//4、定义sql
String sql = "select * from user";
//4、执行sql
result= statement.executeQuery(sql); //返回的是结果集
//5、遍历结果集
while(result!=null&&result.next()){
❤❤❤//在结果集中取数据,需要根据表中数据类型来取
result.getInt("id");
String u1=result.getString("uname");
String p1=result.getString("pword");
if(u.equals(u1)&&p.equals(p1)){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//6、关闭数据库资源(从下往上关闭)
try {
if(result!=null) {
result.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
//要做一下判空,否则会报空指针异常,体现程序严谨
if(statement!=null){
statement.close(); //关闭资源statement
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close(); //关闭资源connection
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
法二:直接用sql语句查询
*/
import java.sql.*;
import java.util.Scanner;
public class JDBCDemo02 {
public static void main(String[] args) {
Connection connection =null;
PreparedStatement statement =null;
ResultSet result=null;
Scanner sc1=new Scanner(System.in);
System.out.print("请输入用户名:");
String u=sc1.next();
Scanner sc2=new Scanner(System.in);
System.out.print("请输入密码:");
String p=sc2.next();
//连接数据库
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zj1" +
"?serverTimezone=GMT&characterEncoding=utf8", "root", "123");
//3、定义sql
String sql = "select * from user where uname=? and pword=?"; //?表示占位符
//4、获取数据库操作对象解析sql
statement = connection.prepareStatement(sql);
//给占位符赋值(键盘输入的值)
statement.setString(1,u);
statement.setString(2,p);
//4、执行sql
result= statement.executeQuery(); //返回的是结果集
//5、遍历结果集
if(result!=null&&result.next()){
System.out.println("成功");
}else{
System.out.println("失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//6、关闭数据库资源
try {
if(result!=null) {
result.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
//要做一下判空,否则会报空指针异常,体现程序严谨
if(statement!=null){
statement.close(); //关闭资源statement
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close(); //关闭资源connection
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
需求2:
1、创建用户表,在程序中创建User实体
2、通过JDBC添加5条数据到表中
3、将数据读取出来,读取的每条数据封装成user对象,将每个user、对象添加到集合中
4、遍历集合
- PreparedStatement:
- 是Statement的子接口,能使sql语句保存为编译模式,先将sql的逻辑框架提交,再去数据库里提取数据
- Statement是将整个sql提交,会造成sql注入
/**
首先创建User类,还需要用到PreparedStatement及占位符
*/
public class JDBCDemo02 {
public static void main(String[] args) {
Connection connection =null;
PreparedStatement statement =null;
ResultSet result=null;
//连接数据库
try {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zj1" +
"?serverTimezone=GMT&characterEncoding=utf8", "root", "123");
//sql添加
String sql1 = "insert into user(uname,pword) values(?,?)";
//解析sql
String a="xq";
String b="888";
statement = connection.prepareStatement(sql1);
statement.setString(1,a);
statement.setString(2,b);
//4、执行sql(注意:当用到占位符时,不用把sql带入executeUpdate(中))
int num = statement.executeUpdate();
System.out.println(num == 1 ? "修改成功" : "修改失败");
//sql查
String sql2 = "select uname,pword from user";
result =statement.executeQuery(sql2);
//创建集合实例
ArrayList<User> users=new ArrayList<>();
//遍历结果集,并封装进User类
while(result!=null&&result.next()){
String u1=result.getString("uname");
String p1=result.getString("pword");
User user=new User(u1,p1);
users.add(user);
}
//遍历集合ArrayList:users,并输出
for (User us:users
) {
System.out.println(us);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//6、关闭数据库资源
try {
if(result!=null) {
result.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
//要做一下判空,否则会报空指针异常,体现程序严谨
if(statement!=null){
statement.close(); //关闭资源statement
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close(); //关闭资源connection
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.3 案例1 JDBC两张表
需求:
1、创建学生表student,字段:编号、姓名、年龄、性别、爱好、出生日期、家庭住址、所属班级
2、创建班级表class,字段:班级id,班级名称
3、通过jdbc添加数据
4、通过jdbc查询数据,将班级数据和学生数据封装成对象添加到集合中
5、遍历集合,打印每个学生信息及所属班级
1.4 创建JDBC工具类
- 工具类特点
- 所有方法都是静态的(可以拿着类名直接调用,不用创建实例)
- 构造方法私有化(不希望在外界创建工具类的实例)
- 工具类的作用
- 简化开发,将一些频繁使用且臃肿繁琐的代码封装成一个工具类
import java.sql.*;
/**
* JDBC工具类(六大步骤封装)
*/
public class JDBCUtils {
/**
* 加载驱动
*/
static{
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 建立连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/zj1?" +
"serverTimezone=GMT&characterEncoding=utf8", "root", "123");
}
/**
* 关闭资源
* @param resultset
* @param statement
* @param connection
*/
public static void getClose(ResultSet resultset, Statement statement,Connection connection){
if(resultset!=null){
try {
resultset.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2. JAVA事务
2.1 知识点
- ACID原则(面试)
- 原子性
- 事务执行过程中,任何失败都将导致事务所做的任何修改失败
- 一致性
- 事务失败时,所有被该事务影响的数据都应该恢复到事务执行前状态
- 隔离性
- 事务执行过程中对数据的修改,在事务提交前对其他事务不可见
- 持久性
- 已提交的数据在事务执行失败时,数据的状态都应该正确
- 原子性
2.2 案例1 银行两个账户转账
需求:
1、创建银行数据库account,字段:id,balanceA,balanceB
2、实现两个账户之间的转账,保证事务特性(开启java事务)
//JDBC工具类,自己编写,直接调用,
//JDBC六大步骤换汤不换药
import ygkj.zj.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class AcountJDBC {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement statement=null;
try {
//连接数据库
connection = JDBCUtils.getConnection();
connection.setAutoCommit(false); //开启事务,并设置手动提交
statement=connection.prepareStatement("update account set balanceA = balanceA - ? where id=?");
statement.setDouble(1,1000.00); //给占位符赋值
statement.setInt(2,1);
int num1=statement.executeUpdate();
System.out.println(num1==1?"扣钱成功":"扣钱失败");
statement=connection.prepareStatement("update account set balanceB = balanceB + ? where id=?");
statement.setDouble(1,1000.00);
statement.setInt(2,1);
//检验是否修改成功
int num2=statement.executeUpdate();
System.out.println(num2==1?"加钱成功":"加钱失败");
connection.commit(); //手动提交事务
} catch (SQLException e) {
//回滚事务,希望事务回到最初状态
try {
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭数据库资源
JDBCUtils.getClose(null,statement,connection);
}
}
}
/**
如果中间出现错误,就不会提交事务,
即数据库中数据不会被更改,体现了java事务控制程序完成
*/