Java研学-jdbc(二)
2023-12-13 17:46:13
六 代码重构
??对于需要反复编写的这种代码,可以将其抽取到工具类中,简化开发,以及将可能会修改的值抽取到properties文件中,解决硬编码的问题
工具类
public class JDBCUtil {
private static Connection connection=null;
/*加载驱动创建连接只需要执行一次*/
static {
try {
//创建Properties对象
Properties properties=new Properties();
//加载外面的配置文件 通过当前线程获取类加载器,从而获取当前项目根路径下的文件
InputStream is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("db.properties");
properties.load(is);
//读取外部配置文件的内容
String driver = properties.getProperty("jdbc.driver");
String url = properties.getProperty("jdbc.url");
String user = properties.getProperty("jdbc.user");
String password = properties.getProperty("jdbc.password");
Class.forName(driver);
connection= DriverManager.getConnection(url,user,password);
} catch (Exception e) {
e.printStackTrace();
}
}
/*加载驱动创建连接对象*/
public static Connection getConnection(){
return connection;
}
/*关闭对象释放资源*/
public static void close(Connection connection,Statement statement,ResultSet resultSet){
try {
if (resultSet!=null){
resultSet.close();
}
if (statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///web_crud
jdbc.user=root
jdbc.password=root
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Long id;
private String ename;
private String job;
private String eid;
private Integer salary;
}
接口
public interface IEmployeeDao {
//修改员工
public void updateEmployee(Employee employee);
//增加员工
public void addEmployee(Employee employee);
//根据id查询员工
public Employee queryById(int id);
//查询所有
public List<Employee> queryALl();
}
实现类
public class EmployeeDaoImpl implements IEmployeeDao {
/*修改员工*/
@Override
public void updateEmployee(Employee employee) {
try {
// 使用工具类创建连接对象
Connection connection = JDBCUtil.getConnection();
String sql="update t_employee set eid=? ,ename=? ,job=?,salary=? WHERE id=?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setObject(1,employee.getEid());
statement.setObject(2,employee.getEname());
statement.setObject(3,employee.getJob());
statement.setObject(4,employee.getSalary());
statement.setObject(5,employee.getId());
statement.executeUpdate();
JDBCUtil.close(connection,statement,null);
} catch (Exception e) {
e.printStackTrace();
}
}
/*增加员工*/
@Override
public void addEmployee(Employee employee) {
try {
Connection connection = JDBCUtil.getConnection();
String sql="insert into t_employee(eid,ename,job,salary)values(?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setObject(1,employee.getEid());
statement.setObject(2,employee.getEname());
statement.setObject(3,employee.getJob());
statement.setObject(4,employee.getSalary());
statement.executeUpdate();
JDBCUtil.close(connection,statement,null);
} catch (Exception e) {
e.printStackTrace();
}
}
/*根据id查询*/
@Override
public Employee queryById(int id) {
try {
Connection connection = JDBCUtil.getConnection();
String sql="SELECT * from t_employee WHERE id=?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setObject(1,id);
//执行查询:将查询的员工信息封装在返回结果集对象中
ResultSet resultSet = statement.executeQuery();
//遍历集合
Employee employee=null;
while (resultSet.next()){//当遍历的集合中有数据,就获取里面的信息
//循环依次获取数据库表的一行数据
//获取字段信息
Long tid = resultSet.getLong("id");
String eid = resultSet.getString("eid");
String ename = resultSet.getString("ename");
String job = resultSet.getString("job");
int salary = resultSet.getInt("salary");
//创建员工对象:使用有参构造实例化对象
employee=new Employee(tid,eid,ename,job,salary);
}
JDBCUtil.close(connection,statement,resultSet);
//返回员工对象
return employee;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//查询所有
@Override
public List<Employee> queryALl() {
try {
Connection connection = JDBCUtil.getConnection();
String sql="SELECT * FROM t_employee";
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
//创建返回的集合对象
List<Employee> list=new ArrayList<>();
//遍历结果对象
while (resultSet.next()){
//获取每个员工表数据的列字段信息
Long tid = resultSet.getLong("id");
String eid = resultSet.getString("eid");
String ename = resultSet.getString("ename");
String job = resultSet.getString("job");
int salary = resultSet.getInt("salary");
//将获取的数据封装到员工对象
Employee employee=new Employee(tid,eid,ename,job,salary);
//将员工对象添加到集合中
list.add(employee);
}
JDBCUtil.close(connection,statement,resultSet);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
数据库表
CREATE TABLE `t_employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`eid` varchar(10) NOT NULL,
`ename` varchar(6) NOT NULL,
`job` varchar(10) DEFAULT NULL,
`salary` int(10) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `eid` (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
七 事务
1 概述
??事务是指将一组操作括为一个单元,为确保数据库中数据的一致性,数据操作是成组的单元,当单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
2 事务的 ACID 属性 – 作用
??① 原子性(Atomicity): 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
??②一致性(Consistency): 保证数据的完整性,数据不被破坏,事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
??③ 隔离性(Isolation): 指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
??④ 持久性(Durability): 指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
3 操作步骤
??① 先定义开始一个事务,然后对数据作修改操作,
??② 执行过程中,如果没有问题就提交(commit)事务,此时的修改将永久地保存下来
??③ 如果执行过程中有问题(异常),回滚事务(rollback),数据库将放弃本次事务的所有修改回到开始事务时的状态。
4 例子 – 转账操作
不使用事务 – 异常会导致账户金额问题
public class AccountTest {
public static void main(String[] args) throws Exception {
//1.创建连接对象
Connection connection = JDBCUtil.getConnection();
//2.创建sql执行对象
String sql="SELECT * from account WHERE name='大黄'";
PreparedStatement statement = connection.prepareStatement(sql);
//3.执行查询转出账号的余额查询
ResultSet resultSet = statement.executeQuery();
if (!resultSet.next()){
System.out.println("账号不存在!");
return;
}
//判断余额是否大于500
BigDecimal balance = resultSet.getBigDecimal("balance");
if (balance.intValue()<5000){
System.out.println("目标账号余额不足!");
return;
}
//4.执行转出操作
String sql1="update account set balance =balance- 5000 WHERE name='大黄'";
statement = connection.prepareStatement(sql1);
statement.executeUpdate();
//模拟异常
int num= 1/0;
//5.执行转入操作
String sql2="update account set balance =balance+ 5000 WHERE name='大白'";
statement = connection.prepareStatement(sql2);
statement.executeUpdate();
//6.关闭对象
JDBCUtil.close(connection,statement,resultSet);
}
}
使用事务
public class AccountTXTest {
public static void main(String[] args) {
Connection connection=null;
try {
//1.创建连接对象
connection = JDBCUtil.getConnection();
//开启事务手动提交
connection.setAutoCommit(false);
//2.创建sql执行对象
String sql="SELECT * from account WHERE name='大黄'";
PreparedStatement statement = connection.prepareStatement(sql);
//3.执行查询转出账号的余额查询
ResultSet resultSet = statement.executeQuery();
if (!resultSet.next()){
System.out.println("账号不存在!");
return;
}
//判断余额是否大于500
BigDecimal balance = resultSet.getBigDecimal("balance");
if (balance.intValue()<5000){
System.out.println("目标账号余额不足!");
return;
}
//4.执行转出操作
String sql1="update account set balance =balance- 5000 WHERE name='大黄'";
statement = connection.prepareStatement(sql1);
statement.executeUpdate();
//模拟异常
//int num= 1/0;
//5.执行转入操作
String sql2="update account set balance =balance+ 5000 WHERE name='大白'";
statement = connection.prepareStatement(sql2);
statement.executeUpdate();
//手动提交事务
connection.commit();
System.out.println("转账成功,提交事务!");
//6.关闭对象
JDBCUtil.close(connection,statement,resultSet);
} catch (Exception e) {
System.out.println("转账异常,回滚事务!");
e.printStackTrace();
try {
//转帐出现异常,回滚事务
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
工具类
public class JDBCUtil {
private static Connection connection=null;
/*加载驱动创建连接只需要执行一次*/
static {
try {
Class.forName("com.mysql.jdbc.Driver");
connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
return connection;
}
public static void close(Connection connection,Statement statement,ResultSet resultSet){
try {
if(connection!=null){
connection.close();
}
if (statement!=null){
statement.close();
}
if (resultSet!=null){
resultSet.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据库表
CREATE TABLE account(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20),
balance DECIMAL(10,2)
);
INSERT INTO account(name,balance) VALUES('大黄',18000),('大白',0);
5 小结
① 默认事务在执行完 DML 操作就自动提交.
② 查询操作,不需要事务
③ 代码正确无异常,但数据库数据不变,有可能是没有提交事务
④ MySQL ,中 InnoDB 存储引擎支持事务,支持外键,MyISAM 不支持事务.
文章来源:https://blog.csdn.net/zhlyxx/article/details/134974618
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!