JAVA连接数据库

JAVA连接数据库,第1张

JAVA *** 作两表关系

四种:双向一对一,一对多,多对一,多对多

多表关系处理数据

(1) 数据库通过外键建立两表关系

(2) 实体类通过属性的方式建立两表关系

实体类要求:类名=表名,列名=属性名

一对多(老师->学生)

 学生表

老师表

 学生实体类

package com.bean;

//多方,多个学生可以对应一个老师
//实体类要求:类名=表名,列名=属性名
public class Student {
    private int stuId;
    private String stuName;
    private int teacherId;

    public int getStuId() {
        return stuId;
    }

    public void setStuId(int stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(int teacherId) {
        this.teacherId = teacherId;
    }
}

老师实体类

package com.bean;

import java.util.List;

//一方,一个老师可以对应多个学生
//实体类要求:类名=表名,列名=属性名
public class Teacher {
    private int tid;
    private String tname;
    //在一方创建存储多方数据的集合
    private List studentList;

    public int getTid() {
        return tid;
    }

    public void setTid(int tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public List getStudentList() {
        return studentList;
    }

    public void setStudentList(List studentList) {
        this.studentList = studentList;
    }
}

Dao包,定义 *** 作方法的接口

package com.dao;

import com.bean.Teacher;

public interface TeacherDao {
    //定义 *** 作方法
    //根据老师id查询老师信息,包含学生的信息
    public Teacher getById(int tid);
}

实现Dao包里的接口,定义实体 *** 作方法

package com.dao.impl;

import com.bean.Student;
import com.bean.Teacher;
import com.dao.TeacherDao;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class TeacherDaoImpl implements TeacherDao {
    @Override
    public Teacher getById(int tid) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //3.通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
            //JDBC中的所有参数都由?符号,这被称为参数标记。
            String sql = "SELECT * FROM student s,teacher t WHERE s.`teacherid`=t.`tid` AND t.`tid`=?";
            preparedStatement = connection.prepareStatement(sql);
            //4.参数填充,占位符赋值,下标从1开始
            preparedStatement.setInt(1, tid);
            //5.通过预编译sql语句和传入的参数查询语句查到结果集
            resultSet = preparedStatement.executeQuery();
            Teacher t = new Teacher();
            //创建集合存储学生信息
            List studentList = new ArrayList<>();
            //6.取出结果集
            while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
                //1.取出各自的信息
                //因为是一对多的关系,通过老师的id查询学生,老师的信息是不变的,学生的信息每行都是变化的
                String tname = resultSet.getString("tname");
                int teacherId = resultSet.getInt("tid");
                //将查询的结果赋值到Teacher对象里
                t.setTid(teacherId);
                t.setTname(tname);
               //因为是一对多的关系,通过老师的id查询学生,老师的信息是不变的,学生的信息每行都是变化的
                Student student = new Student();
                student.setStuId(resultSet.getInt("stuid"));
                student.setStuName(resultSet.getString("stuname"));
                //建立学生和老师之间的关系
                studentList.add(student);
            }
            //将学生对象的集合添加到老师对象里
            t.setStudentList(studentList);
            return t;


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return null;
    }
}

测试类 

package com.test;

import com.bean.Student;
import com.bean.Teacher;
import com.dao.TeacherDao;
import com.dao.impl.TeacherDaoImpl;

import java.util.List;

public class Demo1 {
    public static void main(String[] args) {
        TeacherDao teacherDao = new TeacherDaoImpl();
        Teacher teacher = teacherDao.getById(1);
        System.out.println("老师姓名" + teacher.getTname());
        System.out.println("老师id" + teacher.getTid());
        List studentList = teacher.getStudentList();
        for (Student student : studentList) {
            System.out.println("学生姓名" + student.getStuName());
        }
        /*老师姓名张三老师
        老师id1
        学生姓名bb
        学生姓名dd
        学生姓名ee*/
    }
}

多对一(学生->老师)

多名学生对应一个老师

package com.bean;

//多方,多个学生可以对应一个老师
//实体类要求:类名=表名,列名=属性名
public class Student {
    private int stuId;
    private String stuName;
    private int teacherId;
    //多对一,在多方创建一个存储一方数据的对象
    private Teacher teacher;

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public int getStuId() {
        return stuId;
    }

    public void setStuId(int stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(int teacherId) {
        this.teacherId = teacherId;
    }
}
public List getAll() {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    // *** 作数据库
    //1.加载驱动
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.通过驱动管理器获取jdbc连接对象
        String userName = "root";
        String passWord = "123456";
        String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
        connection = DriverManager.getConnection(url, userName, passWord);
        //3.通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
        //JDBC中的所有参数都由?符号,这被称为参数标记。
        String sql = "SELECT * FROM student s,teacher t WHERE s.`teacherid`=t.`tid` ";
        preparedStatement = connection.prepareStatement(sql);
        //4.通过预编译sql语句和传入的参数查询语句查到结果集
        resultSet = preparedStatement.executeQuery();
        //创建集合存储学生对象也包含老师对象
        List studentList = new ArrayList<>();
        //5.取出结果集
        while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
            //1.取出各自的信息
            Student student = new Student();
            student.setStuId(resultSet.getInt("stuid"));
            student.setStuName(resultSet.getString("stuname"));

            Teacher teacher = new Teacher();
            String tname = resultSet.getString("tname");
            int teacherId = resultSet.getInt("tid");
            //将查询的结果赋值到Teacher对象里
            teacher.setTid(teacherId);
            teacher.setTname(tname);

            //将老师的信息赋值到学生对象里
            student.setTeacher(teacher);
    
            //将查询到的一行数据学生老师的都添加到集合里
            studentList.add(student);
        }

        return studentList;
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (preparedStatement != null) {
                preparedStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return null;
}
List all = teacherDao.getAll();
for (Student student : all) {
    System.out.println(student.getStuId() + "," +
            student.getStuName() + "," +
            "老师姓名" + student.getTeacher().getTname());
}
/*1,aaa,老师姓名王五
2,bb,老师姓名张三老师
3,cc,老师姓名王五
4,dd,老师姓名张三老师
5,ee,老师姓名张三老师
6,ff,老师姓名李四老师*/
一对一(妻子丈夫)

 

  

package com.bean;

//丈夫实体类
public class Husband {
    private int hid;
    private String husName;
    //双向一对一关系,在各自的类中创建对象
    private Wife wife;

    public int getHid() {
        return hid;
    }

    public void setHid(int hid) {
        this.hid = hid;
    }

    public String getHusName() {
        return husName;
    }

    public void setHusName(String husName) {
        this.husName = husName;
    }

    public Wife getWife() {
        return wife;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

-------------------------------------------------------------------------
package com.bean;
//妻子实体类
public class Wife {
    private int wifeId;
    private String wifeName;
    private int hid;
    private Husband husband;

    public int getWifeId() {
        return wifeId;
    }

    public void setWifeId(int wifeId) {
        this.wifeId = wifeId;
    }

    public String getWifeName() {
        return wifeName;
    }

    public void setWifeName(String wifeName) {
        this.wifeName = wifeName;
    }

    public int getHid() {
        return hid;
    }

    public void setHid(int hid) {
        this.hid = hid;
    }

    public Husband getHusband() {
        return husband;
    }

    public void setHusband(Husband husband) {
        this.husband = husband;
    }
}
-------------------------------------------------------------------------
package com.dao;

import com.bean.Husband;
import com.bean.Wife;

public interface WideDao {
    //查询妻子信息(包含丈夫信息)
    public Wife getWife(int wid);

    //查询丈夫信息(包含妻子信息)
    public Husband getHus(int hid);
}
-------------------------------------------------------------------------
package com.dao.impl;

import com.bean.Husband;
import com.bean.Student;
import com.bean.Teacher;
import com.bean.Wife;
import com.dao.WideDao;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class WifeDaoImpl implements WideDao {
    @Override
    public Wife getWife(int wid) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //3.通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
            //JDBC中的所有参数都由?符号,这被称为参数标记。
            String sql = "SELECT* FROM wife,husband WHERE wife.`hid`=husband.`husid` AND wifeid=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, wid);
            //4.通过预编译sql语句和传入的参数查询语句查到结果集
            resultSet = preparedStatement.executeQuery();
            Wife wife = new Wife();
            //5.取出结果集
            while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
                wife.setWifeId(resultSet.getInt("wifeid"));
                wife.setWifeName(resultSet.getString("wifename"));
                Husband husband = new Husband();
                husband.setHid(resultSet.getInt("husid"));
                husband.setHusName(resultSet.getString("husname"));
                //建立两表关系
                wife.setHusband(husband);
            }
            return wife;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Husband getHus(int hid) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //3.通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
            //JDBC中的所有参数都由?符号,这被称为参数标记。
            String sql = "SELECT* FROM wife,husband WHERE wife.`hid`=husband.`husid` AND husid=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, hid);
            //4.通过预编译sql语句和传入的参数查询语句查到结果集
            resultSet = preparedStatement.executeQuery();
            Husband husband = new Husband();
            //5.取出结果集
            while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
                husband.setHid(resultSet.getInt("husid"));
                husband.setHusName(resultSet.getString("husname"));
                Wife wife = new Wife();
                wife.setWifeId(resultSet.getInt("wifeid"));
                wife.setWifeName(resultSet.getString("wifename"));
                //建立两表关系
                husband.setWife(wife);
            }
            return husband;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
多对多(科目-学生)

一个科目可以包含多个学生,一个学生也可以学习多个科目

 

 

package com.bean;

import java.util.List;

//多方,多个学生可以对应一个老师
//实体类要求:类名=表名,列名=属性名
public class Student {
    private int stuId;
    private String stuName;
    private int teacherId;
    //多对一,在多方创建一个存储一方数据的对象
    private Teacher teacher;

    //多对多关系,一个学生对应多个科目
    private List subjectList;

    public List getSubjectList() {
        return subjectList;
    }

    public void setSubjectList(List subjectList) {
        this.subjectList = subjectList;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public int getStuId() {
        return stuId;
    }

    public void setStuId(int stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(int teacherId) {
        this.teacherId = teacherId;
    }
}
————————————————————————————————————————————————————————————————————————————————————————
package com.bean;

import java.util.List;

public class Subject {
    private int subId;
    private String subName;
    //多对多关系,一个科目对应多个学生
    private List studentList;

    public int getSubId() {
        return subId;
    }

    public void setSubId(int subId) {
        this.subId = subId;
    }

    public String getSubName() {
        return subName;
    }

    public void setSubName(String subName) {
        this.subName = subName;
    }

    public List getStudentList() {
        return studentList;
    }

    public void setStudentList(List studentList) {
        this.studentList = studentList;
    }
}
————————————————————————————————————————————————————————————————————————————————————————
package com.dao;

import com.bean.Student;
import com.bean.Subject;

public interface SubjectDao {
    //听过学生id找到信息,包含科目信息
    public Student getByStuId(int stuId);
    //听过科目id找到信息,包含学生信息
    public Subject getBySubId(int subId);
}
————————————————————————————————————————————————————————————————————————————————————————
package com.dao.impl;

import com.bean.Student;
import com.bean.Subject;
import com.bean.Teacher;
import com.dao.SubjectDao;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class SubjectDaoImpl implements SubjectDao {
    @Override
    public Student getByStuId(int stuId) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
            //JDBC中的所有参数都由?符号,这被称为参数标记。
            String sql = " SELECT * FROM student s,SUBJECT sub,middle m WHERE s.`stuid`=m.`stuid`AND sub.`subid`=m.`subid` AND s.`stuid`=? ";
            preparedStatement = connection.prepareStatement(sql);
            //传参给占位符
            preparedStatement.setInt(1, stuId);
            //通过预编译sql语句和传入的参数查询语句查到结果集
            resultSet = preparedStatement.executeQuery();
            //创建学生对象,因为要查询的是学生,学生信息是不变的,一个学生对应多个科目
            Student student = new Student();
            //创建集合存储科目对象,一个学生对应多个科目
            List subjectList = new ArrayList<>();
            //取出结果集
            while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
                //取出各自的信息
                student.setStuId(resultSet.getInt("stuid"));
                student.setStuName(resultSet.getString("stuname"));
                Subject subject = new Subject();
                subject.setSubId(resultSet.getInt("subid"));
                subject.setSubName(resultSet.getString("subname"));
                //将查询到的一行学科对象添加到集合中
                subjectList.add(subject);
            }
            //将学科对象的集合传到学生对象里
            student.setSubjectList(subjectList);
            return student;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Subject getBySubId(int subId) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //通过jdbc连接对象创建sql语句预编译执行环境对象,传入预编译的SQL语句
            //JDBC中的所有参数都由?符号,这被称为参数标记。
            String sql = " SELECT * FROM student s,SUBJECT sub,middle m WHERE s.`stuid`=m.`stuid`AND sub.`subid`=m.`subid` AND sub.`subid`=? ";
            preparedStatement = connection.prepareStatement(sql);
            //传参给占位符
            preparedStatement.setInt(1, subId);
            //通过预编译sql语句和传入的参数查询语句查到结果集
            resultSet = preparedStatement.executeQuery();
            //创建学科对象,因为要查询的是学科,学科信息是不变的,一个学科对应多个学生
            Subject subject = new Subject();
            //创建集合存储学生对象,一个学科对应多个学生
            List studentList = new ArrayList<>();
            //取出结果集
            while (resultSet.next()) {//一个while循环每走一次遍历的是一行数据
                //取出各自的信息
                subject.setSubId(resultSet.getInt("subid"));
                subject.setSubName(resultSet.getString("subname"));

                Student student = new Student();
                student.setStuId(resultSet.getInt("stuid"));
                student.setStuName(resultSet.getString("stuname"));
                //将查询到的一行学生对象添加到集合中
                studentList.add(student);
            }
            //将学生对象的集合传到学科对象里
            subject.setStudentList(studentList);
            return subject;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}



事务

database transaction

概述: 将多条SQL语句, 看作一个整体. 要么一起成功, 要么一起失败.

特点:可以保证数据的原子性,持久性和一致性,可以解决数据在进行多线程 *** 作时,出错的问题

事务在mysql中, 是默认自动提交的 .

事务面试题:

(ACID)

1.请描述事务的四大特征 :

<1>.   actomicity(原子性)   一个事务是一个整体 , 执行结果的成功与否不可分割 , 要么同时成功, 要么同时失败.往数据库中添加100条数据,要么一起成功要么一起失败

<2>.   consistency(一致性)   事务 *** 作的前后 , 数据总量不变 表示一个事务内有一个 *** 作失败时,所有的更改过的数据都必须回滚到修改前状态,回滚之后的数据和原来的数据一致。

<3>.  isolation(隔离性) 并发情况下,多个事务之间, 隔离开, 相互独立.一个事务未提交的数据,另一个事务是无法读取的。

<4>.  durability(持久性):   当事务提交或回滚后, 数据库会持久化的保存事务对数据库的影响.

2.请描述什么是脏读, 幻读, 不可重复读 ?

<1>. 脏读: 一个事务读取到了另一个事务未提交的数据.

<2>.   不可重复读: 事务A读取了两次某数据, 在两次读取过程中另一个事务修改了数据, 导致事务A两次读取的结果不一致.与幻读很像, 但是不可重复读强调的是单条数据的更改.

<3>.幻读: 事务A读取了两次某表格的数据, 在两次读取过程中另一个事务为表格新增了行, 导致事务A两次读取的结果行数有差异.与不可重复读很像,但是幻读强调的是一个表格的行的增减

3. 请描述事务的隔离级别

<1>. 读未提交   :   read uncommitted; (可能产生:脏读, 不可重复读, 幻读)

<2>.   读已提交   :   read committed; (可能产生: 不可重复度, 幻读)

<3>.可重复读   :   repeatable read;(mysql默认值) (可能产生: 幻读)

<4>. 串行化 :   serializable;

JDBC中事务应用

如果JDBC连接处于自动提交模式,默认情况下,则每个SQL语句在完成后都会提交到数据库。

事务使您能够控制是否和何时更改应用于数据库。它将单个SQL语句或一组SQL语句视为一个逻辑单元,如果任何语句失败,则整个事务将失败。

要启用手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用Connection对象的setAutoCommit()方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我们可以传递一个布尔值true来重新打开它。

*** 作方式1: 命令行

-   开启事务:   start transaction;

-   回滚     :   rollback;   --此次事务中所有的sql *** 作, 放弃.

-   提交     :   commit; --此次事务中所有的sql *** 作, 作为一个整体, 提交.

*** 作方式2: Java

JDBC事务通过连接对象开启, 回滚 ,提交. 只针对当前连接对象生效.

默认jdbc事务是自动提交的

-   开启事务:   conn.setAutoCommit(false);

-   回滚事务:   conn.rollback();

-   提交事务:   conn.commit();

try{
//开启手动提交事务,可以在一个事务中 *** 作多次数据
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
String SQL1 = "INSERT INTO Employees values (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL);
//提交一个格式错误的sql语句,会出现异常
String SQL2 = "INSERTED IN Employees VALUES (107, 22, 'Sita', 'Singh')";
stmt.executeUpdate(SQL);
// 如果整个事务没有错误则提交,有错误则回滚
conn.commit();
}catch(SQLException se){
// 有异常则回滚到最初的状态,都没提交
conn.rollback();
}
Savepoints

新的JDBC 3.0 Savepoint接口为您提供了额外的事务控制。

设置保存点时,可以在事务中定义逻辑回滚点。如果通过保存点发生错误,则可以使用回滚方法来撤消所有更改或仅保存在保存点之后所做的更改。

Connection对象有两种新的方法来帮助您管理保存点

- setSavepoint(String savepointName):定义新的保存点。它还返回一个Savepoint对象。

- releaseSavepoint(Savepoint savepointName):删除保存点。请注意,它需要一个Savepoint对象作为参数。此对象通常是由setSavepoint()方法生成的保存点。

try{
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
String SQL1 = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL);
//设置保存点,起名为Savepoint1
Savepoint savepoint1 = conn.setSavepoint("Savepoint1");
//提交一个格式错误的sql语句,会出现异常
String SQL2 = "INSERTED IN Employees VALUES (107, 22, 'Sita', 'Tez')";
stmt.executeUpdate(SQL);
conn.commit();
}catch(SQLException se){
//遇到异常时,回滚到Savepoint1,而Savepoint1保存点执行了SQL1
conn.rollback(savepoint1);
//将SQL1的执行提交,有效的保证有些数据让他部分提交
conn.commit();
}
事务案例-转账

package com.test;

import com.bean.Student;
import com.bean.Subject;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class Demo4 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // *** 作数据库
        //加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //通过驱动管理器获取jdbc连接对象
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            connection = DriverManager.getConnection(url, userName, passWord);
            //开启手动提交事务
            connection.setAutoCommit(false);
            //创建sql执行通道
            Statement statement = connection.createStatement();
            //转账
            int i1 = statement.executeUpdate("UPDATE money SET yue=yue-100 WHERE userid=1");
            //收账
            int i2 = statement.executeUpdate("UPDATE money SET yue=yue+100 WHERE userid=2");
            //打印一个异常,有异常直接回滚,回到数据最初状态
            System.out.println(2/0);
            //事务提交
            connection.commit();
            if (i2 > 0) {
                System.out.println("执行成功");
            } else {
                System.out.println("执行失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

第一种: 没有出现异常,正常状态

在一种执行完之后在代码里加一个异常,出现异常,回滚到第一种执行完后的状态

 

第三种:如果将手动提交关闭,改为自动提交,程序出现异常,数据库事务还是会自动提交,数据库里的 *** 作还是会改变,不符合业务逻辑

  

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/721805.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存