Java学习——JDBC之从导Jar包到封装

书籍就像一盏神灯,它照亮人们最遥远、最黯淡的生活道路。——乌皮特

前言:下面内容是本人Java初学者的学习内容

前提准备:已经安装好mysql数据库,若没有请看Mysql8.0的下载安装
需要学习SQL语句,没有学的请看SQL语句简单学习

一、mysql-connector-java

有了这个Jar包支持,JAVA可以轻松的通过jdbc访问mySQL数据库。

1.下载

进入官网下载地址: https://dev.mysql.com/downloads/connector/j/

如下图操作即可:
在这里插入图片描述
直接点击 “No thanks, just start my download.”

在这里插入图片描述
解压出来即可

在这里插入图片描述

2.导入项目中

(我用的是Idea)

如下图操作:

2.1 新建一个项目工程,再新建一个libs文件夹,用于存放jar包

在这里插入图片描述
在这里插入图片描述

2.2 接着把刚才下载解压好的 mysql-connector-java-8.0.22.jar,ctrl+c 复制,ctrl+v粘贴进libs文件夹

在这里插入图片描述
2.3 导入后,需要激活(有好几种方法,这是其中一种)。打开project-setting(快捷键:ctrl+shirt+alt+s ),点击+号,选择第一个,如下图操作:

在这里插入图片描述
2.4 选择路径,好了后点击0K,就可以了。

在这里插入图片描述

二、JDBC简介

JDBC其实就是Java DataBase Connectivity:Java数据库连接
她所扮演的角色:提供连接数据库服务器的支持(如下图)

在这里插入图片描述

JDBC 重要的 四大物件

DriverManager:注册驱动,选择正确的驱动并加载

Connection:获取连接,由Driver产生,负责与数据库的连接,进行数据传输

Statement:传送SQL语句,由Connection产生,负责将sql语句送到数据库

ResultSet:获取结果集,负责接收Statement(sql)执行后的结果

四大物件关系图:

在这里插入图片描述

三、JDBC的实现

1.初始化驱动

通过 Class.forName(“com.mysql.cj.jdbc.Driver”); 将mysql驱动(com.mysql.cj.jdbc.Driver)注册到DriverManager中去

Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。

2.与数据库进行连接

这里需要提供:
数据库所处于的ip:127.0.0.1 (本机)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称 helloJava(自己建一个)
支持中文 characterEncoding=UTF-8
时区支持 serverTimezone=GMT
账号 root
密码 123456(我就学习用,简单点好)

String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
Connection con= DriverManager.getConnection(url, user, password);
3.SQL语句的执行

Statement的常用方法:
(1)executeQuery()方法:运行查询语句,返回ReaultSet对象。
(2)executeUpdata()方法:运行增,删,改操作,返回更新的行数。
(3)addBatch(String sql) :把多条sql语句放到一个批处理中。
(4)executeBatch():向数据库发送一批sql语句执行。

String sql="insert into hero values(null,'提莫',450.0,56)";
Statement st = con.createStatement();
st.executeUpdate(sql);//执行增删改
st.executeQuery(sql);//执行查询
4.获取结果

结果集:ResultSet
执行executeQuery()方法后返回的结果集

常用方法:
(1)getString(String columnName):获得当前行的某一string类型的字段
(2)getFloat(String columnName):获得当前行的某一string类型的字段
(3)getDate(String columnName):获得当前行的某一date类型的字段
(4)getBoolean(String columnName):获得在当前行的某一Boolean类型的字段
(5)getObject(String columnName):获取当前行的某一任意类型的字段
(6)next():移动到下一行

ResultSet rs = st.executeQuery(sql);
while(rs.next()){
	......
}
5.关闭连接

手动关闭:
数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯
先关闭ResultSet,Statement,再关闭Connection
Close ResultSet,
Close Statement,
close Connection

 //与数据库连接关闭
    public static void close(Connection con, Statement st, ResultSet rs) {
        try {
            if(rs!=null) {
                rs.close();
            }
            if(st!=null) {
                st.close();
            }

            if(con!=null) {
                con.close();
            }
        } catch (SQLException e) {
            System.out.println("关闭失败");
            e.printStackTrace();
        }
    }

自动关闭:
实现了AutoCloseable接口的类可以使用try-with-resource自动关闭连接,这样就不会发生忘记关闭连接。

 try(Connection con= DriverManager.getConnection(url, user, password);
            Statement st = con.createStatement();
        ) {
            String sql="insert into hero values(null,'盖伦',650.0,60)";
            st.executeUpdate(sql);
            System.out.println("sql语句执行成功");

        } catch (SQLException e) {
            System.out.println("数据库操作出错");
            e.printStackTrace();
        }

下面贴上完整的JDBC的代码:

增删改(手动关闭连接)

package priv.jdbc.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) throws ClassNotFoundException {
        //加载驱动类
        Class.forName("com.mysql.cj.jdbc.Driver");
        //获得与数据库的连接
        //DriverManager:选择正确的驱动并加载
        //Connection :与数据库连接
        Connection con=null;
        Statement st=null;
         /*
            建立与数据库的Connection连接
            这里需要提供:
            数据库所处于的ip:127.0.0.1 (本机)
            数据库的端口号: 3306 (mysql专用端口号)
            数据库名称 helloJava
            支持中文 characterEncoding=UTF-8
            时区支持 serverTimezone=GMT
            账号 root
            密码 123456
         */
          String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
            String user = "root";
            String password = "123456";
        try {           
            con= DriverManager.getConnection(url, user, password);
            System.out.println("连接成功....");
        } catch (SQLException e) {
            System.out.println("与数据库连接失败");
            e.printStackTrace();
        }
        String sql="insert into hero values(null,'提莫',450.0,56)";//增
        //String sql="delete from hero where name='提莫'";//删
        //String sql="update hero set hp=500";//改
        //Statement:将sql语句送到数据库中执行
        try {
            st=con.createStatement();
            //执行sql语句
            int row=st.executeUpdate(sql);
            if (row>0) {
                System.out.println("插入成功.....");
            }
        } catch (SQLException e) {
            System.out.println("插入失败 ");
            e.printStackTrace();
        }
        //关闭连接
        // 数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯
        // 先关闭Statement
        //再关闭Connection
      finally {
            if (st!=null) {
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (con!=null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

package priv.jdbc.demo;

public class Hero {
    public String name;
    public float hp;
    public int damage;

    public Hero(String name, float hp, int damage) {
        this.name = name;
        this.hp = hp;
        this.damage = damage;
    }

    public Hero(float hp) {
        this.hp = hp;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getHp() {
        return hp;
    }

    public void setHp(float hp) {
        this.hp = hp;
    }

    public int getDamage() {
        return damage;
    }

    public void setDamage(int damage) {
        this.damage = damage;
    }
}

增删改(自动关闭连接,try-with-resource)

package priv.jdbc.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {

        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user = "root";
        String password = "123456";
        try(Connection con= DriverManager.getConnection(url, user, password);
            Statement st = con.createStatement();
        ) {
            String sql="insert into hero values(null,'盖伦',650.0,60)";
            //String sql="delete from hero where name='提莫'";//删
            //String sql="update hero set hp=500";//改
            st.executeUpdate(sql);
            System.out.println("sql语句执行成功");

        } catch (SQLException e) {
            System.out.println("数据库操作出错");
            e.printStackTrace();
        }
    }
}

查询

package priv.jdbc.demo;

import java.sql.*;

public class SelectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user = "root";
        String password = "123456";
        try(Connection con= DriverManager.getConnection(url, user, password);
            Statement st = con.createStatement();
        ) {
            String sql="select * from hero";
            // 执行查询语句,并把结果集返回给ResultSet
            ResultSet rs = st.executeQuery(sql);
            while (rs.next()) {
                int id = rs.getInt("id");// 可以使用字段名
                String name = rs.getString(2);// 也可以使用字段的顺序
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                System.out.format("id=%d,name=%s,hp=%f,damage=%d %n", id, name, hp, damage);
            }
        } catch (SQLException e) {
            System.out.println("数据库操作出错");
            e.printStackTrace();
        }
    }
}

6.预编译PreparedStatement

它是一個继承 Statement 类的接口。
和 Statement一样,PreparedStatement也是用来负责将sql语句送到数据库执行。

但是Statement:SQL发送到数据库服务器先经过编译再执行。
而PreparedStatement:先预编译SQL 语句,暂存在缓存里面,调用时就可以直接执行了。

与创建Statement不同的是,需要根据sql语句创建PreparedStatement。
除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。

优点1-参数设置

Statement 需要进行字符串拼接,可读性和维护性比较差
String sql = “insert into hero values(null,”+"‘提莫’"+","+313.0f+","+50+")";

PreparedStatement 使用参数设置,可读性好,不易犯错
String sql = “insert into hero values(null,?,?,?)”;

优点2-性能表现

PreparedStatement有预编译机制,性能比Statement更快

优点3-防止SQL注入式攻击

    假设name是用户提交来的数据
    String name = "'盖伦' OR 1=1";
    使用Statement就需要进行字符串拼接
    拼接出来的语句是:
        select * from hero where name = '盖伦' OR 1=1
    因为有OR 1=1,这是恒成立的
    那么就会把所有的英雄都查出来,而不只是盖伦
    如果Hero表里的数据是海量的,比如几百万条,把这个表里的数据全部查出来
    会让数据库负载变高,CPU100%,内存消耗光,响应变得极其缓慢
    而PreparedStatement使用的是参数设置,就不会有这个问题

实践代码,搓搓小手动起来(=!=):

package priv.jdbc.demo;

import java.sql.*;

public class PreparedStatementTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user = "root";
        String password = "123456";

        String sql="insert into hero values (null,?,?,?)";
        try(Connection con= DriverManager.getConnection(url, user, password);
            // 根据sql语句创建PreparedStatement
            PreparedStatement ps = con.prepareStatement(sql);
        ) {
            //设置参数
            ps.setString(1,"战争之影-赫卡里姆");
            ps.setFloat(2,650.0f);
            ps.setInt(3,55);
            //执行
            ps.execute();
        } catch (SQLException e) {
            System.out.println("数据库操作出错");
            e.printStackTrace();
        }
    }

}

7.批处理
   public void adds(List<Hero> list) {
        String sql ="insert into hero values(?,?,?,?)";
        try(Connection con= DbUtils.getConnection();
            PreparedStatement ps = con.prepareStatement(sql);){
            for (Hero h:list) {
               ps.setInt(1,h.getId());
               ps.setString(2,h.getName());
               ps.setFloat(3,h.getHp());
               ps.setInt(4,h.getDamage());
               ps.addBatch();
            }
            int[] arr =ps.executeBatch();
            System.out.println("批量增加:");
            for(int i=0;i<arr.length;i++) {
                System.out.print(arr[i]+" ");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
8.事务

在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

四个特性:

  • 原子性A(atomicity):一组事务,要么成功;要么撤回。
  • 一致性C(consistency):事务执行后,数据库状态与其他业务规则保持一致。如转账业务,无论事务执行成功否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性I(isolation):事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
  • 持久性D(durability):事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性

在事务中的多个操作,要么都成功,要么都失败。
在JDBC中处理事务,都是通过Connection完成的。

同一事务中所有的操作,都在使用同一个Connection对象。(谨记!我是掉过坑…)

  • con.setAutoCommit(false):表示开启事务

  • con.commit():提交结束事务

  • con.rollback():回滚结束事务

JDBC处理事务的代码格式:

try{
     con.setAutoCommit(false);//开启事务
          ......
          con.commit();//try的最后提交事务
     } catch() {
         con.rollback();//回滚事务
 }

MYSQL 表的类型必须是INNODB(现在是默认存储引擎)才支持事务
在Mysql中,只有当表的类型是INNODB的时候,才支持事务,所以需要把表的类型设置为INNODB,否则无法观察到事务.
修改表的类型为INNODB的SQL:
alter table hero ENGINE = innodb;
查看表的类型的SQL
show table status from 数据库名;

实践代码,搓搓小手动起来(=!=):

事务代码:

package priv.jdbc.demo;

import java.sql.*;

public class Business {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user = "root";
        String password = "123456";

        try(Connection con= DriverManager.getConnection(url, user, password)){
            //关闭自动默认提交,开启事务
            con.setAutoCommit(false);
            Boolean OK = true;
            //给id为101和102的hero数据,hp分别减少和增加100
            String sql1 ="update hero set hp = hp - ? where id = ?";
            String sql2 ="update hero set hp = hp + ? where id = ?";
            try (PreparedStatement prs1 = con.prepareStatement(sql1);
                 PreparedStatement prs2 = con.prepareStatement(sql2)) {
                //设置参数
                prs1.setFloat(1,100);
                prs1.setInt(2,100);

                prs2.setFloat(1,100);
                prs2.setInt(2,108);
                //执行语句
                int row1 = prs1.executeUpdate();
                int row2 = prs2.executeUpdate();
                if (row1==0 || row2==0) {
                    OK=false;
                    System.out.println("rollback!");
                    con.rollback();
                }
                if (OK) {
                    //提交事务
                    con.commit();
                    System.out.println("commit!");
                }
            }catch (SQLException e) {
                OK=false;
                con.rollback();
                e.printStackTrace();
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


9.数据库连接池

1.传统方式

当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。
创建连接和关闭连接的过程也是比较消耗时间的,当多线程并发的时候,系统就会变得很卡顿。
同时,一个数据库同时支持的连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光 ,后续线程发起的数据库连接就会失败。

2.连接池

与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。
如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建。 使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。

3.ConnectionPool构造方法和初始化

  1. ConnectionPool() 构造方法约定了这个连接池一共有多少连接
  2. 在init() 初始化方法中,创建了size条连接。 注意,这里不能使用 try-with-resource这种自动关闭连接的方式,因为连接恰恰需要保持不关闭状态,供后续循环使用
  3. getConnection, 判断是否为空,如果是空的就wait等待,否则就借用一条连接出去
  4. returnConnection, 在使用完毕后,归还这个连接到连接池,并且在归还完毕后, 调用notifyAll,通知那些等待的线程,有新的连接可以借用了。
package priv.jdbc.demo;

import priv.jdbc.util.DbUtils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class ConnectionPool {
    List<Connection> cs = new ArrayList<Connection>();

    int size;

    public ConnectionPool(int size) {
        this.size = size;
        init();
    }

    public void init() {

        //这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了
        try {
            for (int i = 0; i < size; i++) {
                Connection c = DbUtils.getConnection();
                cs.add(c);

            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public synchronized Connection getConnection() {
        while (cs.isEmpty()) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        Connection c = cs.remove(0);
        return c;
    }

    public synchronized void returnConnection(Connection c) {
        cs.add(c);
        this.notifyAll();
    }

}

package priv.jdbc.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {

        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user = "root";
        String password = "123456";
        try(Connection con= DriverManager.getConnection(url, user, password);
            Statement st = con.createStatement();
        ) {
            String sql="insert into hero values(null,'盖伦',650.0,60)";
            //String sql="delete from hero where name='提莫'";//删
            //String sql="update hero set hp=500";//改
            st.executeUpdate(sql);
            System.out.println("sql语句执行成功");

        } catch (SQLException e) {
            System.out.println("数据库操作出错");
            e.printStackTrace();
        }
    }
}


四、JDBC的封装

jdbc是连接数据库必不可少的工具,但每次连接都要重新写一遍太麻烦了,也不利于代码的可读性。把重复的代码封装起来,岂不快哉!我查资料看到前辈们把普通的增删改查方法都封装起来了java之对JDBC的完整封装(兼容多种数据库

但是作为新手的我们,还是应该老实的先敲熟练了,再去自己尝试封装各种方法。

简单的封装:把数据库连接和关闭封装起来。

我还学着前辈把项目结构整了一下,什么包放什么类,清晰多了。

在这里插入图片描述

1.包util里的类DbUtils里封装的是Connection 数据库 的连接和关闭。

package priv.jdbc.util;

import java.sql.*;

public class DbUtils {
    //与数据库连接
    public static Connection getConnection() throws ClassNotFoundException {
        String driver ="com.mysql.cj.jdbc.Driver";
        Class.forName(driver);
        String url ="jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
        String user ="root";
        String password = "123456";
        Connection con=null;
        try{
             con = DriverManager.getConnection(url, user, password);
        } catch (SQLException  e) {
            System.out.println("与数据库连接失败");
            e.printStackTrace();
        }
        return con;
    }

    //与数据库连接关闭(增删改查方法里使用try-with-resources语句,会自动关闭连接,但是无法用于数据库连接池)
    public static void close(Connection con, PreparedStatement ps) {
        try{
            if(ps!=null) {
                ps.close();
            }
            if(con!=null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Connection con, PreparedStatement ps, ResultSet rs) {
        try {
            if(rs!=null) {
                rs.close();
            }
            if(ps!=null) {
                ps.close();
            }
            if(con!=null) {
                con.close();
            }
        } catch (SQLException e) {
            System.out.println("关闭失败");
            e.printStackTrace();
        }
    }

}

2.包model里放一张表一个类,比如Hero

package priv.jdbc.model;

public class Hero {
    public int id;
    public String name;
    public float hp;
    public int damage;

    public Hero() {
    }

    public Hero(int id, String name, float hp, int damage) {
        this.id = id;
        this.name = name;
        this.hp = hp;
        this.damage = damage;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getHp() {
        return hp;
    }

    public void setHp(float hp) {
        this.hp = hp;
    }

    public int getDamage() {
        return damage;
    }

    public void setDamage(int damage) {
        this.damage = damage;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", hp=" + hp +
                ", damage=" + damage +
                '}'+"\n";
    }
}

3.包dao里面放操作方法,HeroDao是实现类,去实现接口Dao。

package priv.jdbc.dao;

import priv.jdbc.model.Hero;

import java.sql.Connection;
import java.util.List;

public interface Dao {
    //增
    public int add(Hero hero) ;
    //批处理-增
    public void adds(List<Hero> list);
    //删
    public int delete(int id);
    //改(事务)
    public int updateHp(Connection con,Hero hero, String sql);
    //查
    public Hero select(int id);
    //分页查询
    public List<Hero> list(int start,int count);
}

package priv.jdbc.dao;

import priv.jdbc.model.Hero;
import priv.jdbc.util.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class HeroDao implements Dao {

    /**
     * 增
     * @param hero
     * @throws ClassNotFoundException
     */
    @Override
    public int add(Hero hero) {
        String sql ="insert into hero values(?,?,?,?)";
        int rows=0;
        try(Connection con= DbUtils.getConnection();
            PreparedStatement ps = con.prepareStatement(sql);) {
            ps.setInt(1,hero.getId());
            ps.setString(2,hero.getName());
            ps.setFloat(3,hero.getHp());
            ps.setInt(4,hero.getDamage());
            rows = ps.executeUpdate();//rows>0,表示sql语句执行成功
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return rows;
    }

    /**
     * 批量增加
     * @param list
     */
    @Override
    public void adds(List<Hero> list) {
        String sql ="insert into hero values(?,?,?,?)";
        try(Connection con= DbUtils.getConnection();
            PreparedStatement ps = con.prepareStatement(sql);){
            for (Hero h:list) {
               ps.setInt(1,h.getId());
               ps.setString(2,h.getName());
               ps.setFloat(3,h.getHp());
               ps.setInt(4,h.getDamage());
               ps.addBatch();
            }
            int[] arr =ps.executeBatch();
            System.out.println("批量增加:");
            for(int i=0;i<arr.length;i++) {
                System.out.print(arr[i]+" ");
            }
            System.out.println("");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 删
     * @param id
     * @return
     */
    @Override
    public int delete(int id) {
        String sql = "delete from hero where id="+id;
        int rows=0;
        try (Connection con= DbUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql);){
             rows = ps.executeUpdate();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return rows;
    }

    /**
     * 改
     * @param hero
     * @return
     */
    @Override
    public int updateHp(Connection con,Hero hero,String sql) {
        int rows=0;
        try (
            PreparedStatement ps = con.prepareStatement(sql)){
            ps.setFloat(1, 100);
            ps.setInt(2,hero.id);
            rows = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rows;
    }

    /**
     * 查询
     * @param id
     * @return
     */
    @Override
    public Hero select(int id) {
        Hero hero =null;
        String sql = "select * from hero where id="+id;
        try(Connection con= DbUtils.getConnection();
            PreparedStatement ps = con.prepareStatement(sql);) {
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                String name = rs.getString(2);
                float hp = rs.getFloat(3);
                int damage = rs.getInt(4);
                hero = new Hero(id,name,hp,damage);
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return hero;
    }

    /**
     * 分页查询
     * @param start
     * @param count
     * @return
     */
    @Override
    public List<Hero> list(int start, int count) {
        List<Hero> heros = new ArrayList<Hero>();
        String sql = "select * from hero order by id limit ?,?";
        try(Connection con= DbUtils.getConnection();
            PreparedStatement ps = con.prepareStatement(sql);) {
            ps.setInt(1,start);
            ps.setInt(2,count);
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString(2);
                float hp = rs.getFloat(3);
                int damage = rs.getInt(4);
                Hero hero = new Hero(id,name,hp,damage);
                heros.add(hero);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return heros;
    }
}

4.包service处理事务,比如UpdateService

package priv.jdbc.service;

import priv.jdbc.dao.HeroDao;
import priv.jdbc.model.Hero;
import priv.jdbc.util.DbUtils;

import java.sql.Connection;
import java.sql.SQLException;

public class UpdateService {
    //指定id的hp分别减少和增加100
    public void hpUpdate(Hero h1,Hero h2) {
        HeroDao hd = new HeroDao();
        Boolean OK = true;
        try (Connection con = DbUtils.getConnection()){
            //取消自动提交,事务开启
            con.setAutoCommit(false);
            try {
                String sql1 = "update hero set hp = hp - ? where id = ?";
                String sql2 = "update hero set hp = hp + ? where id = ?";
                int row1 = hd.updateHp(con,h1, sql1);
                int row2 = hd.updateHp(con,h2, sql2);
                if (row1==0 || row2==0) {
                    OK = false;
                    System.out.println("roll back");
                    con.rollback();
                }
                if (OK) {
                    //提交事务
                    con.commit();
                    System.out.println("commit");
                }
            }catch (SQLException e){
                OK=false;
                System.out.println("roll back");
                con.rollback();
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

5.包run放测试类

package priv.jdbc.run;

import priv.jdbc.dao.HeroDao;
import priv.jdbc.model.Hero;
import priv.jdbc.service.UpdateService;

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

public class Test {
    public static void main(String[] args) throws SQLException {
        HeroDao heroDao  =new HeroDao();
        UpdateService us = new UpdateService();
        List<Hero> l = new ArrayList<Hero>();
        Hero hero1 = new Hero(100,"赫卡里姆",675,70);
        Hero hero2 = new Hero(101,"嘉文四世",700,65);
        Hero hero3 = new Hero(102,"沙漠玫瑰",590,75);
        Hero hero4 = new Hero(103,"沙漠玫瑰",590,75);
        Hero hero5 = new Hero(104,"沙漠玫瑰",590,75);
        l.add(hero1);l.add(hero2);
        l.add(hero3);l.add(hero4);
        //批量新增
        heroDao.adds(l);
        //分页查询
        if (heroDao.list(0,5)!=null) {
            System.out.println("分页查询成功,结果如下:");
            System.out.println(heroDao.list(0,5));
        }
        //Hp的增减事务
        us.hpUpdate(hero1,hero2);
        //分页查询
        if (heroDao.list(0,5)!=null) {
            System.out.println("分页查询成功,结果如下:");
            System.out.println(heroDao.list(0,5));
        }
    }
}

还想了解更多:Java自学网站

今天学习分享的内容到此为止了,本是想要激励自己学下去,但发现快乐更是知识在于分享!
作为初学者对于Java的理解实在浅薄,如有错误请指正,万分感谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值