JDBC相关知识

JDBC是一组规范:接口。用于java程序与数据库之间的通信(中间商算是)。

 加载与注册 JDBC 驱动

java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理
器类 (java.sql.DriverManager) 去调用这些 Driver 实现
Oracle 的驱动: oracle.jdbc.driver.OracleDriver
mySql 的驱动: com.mysql.jdbc.Driver
以下我们都使用Mysql的驱动进行连接。

基础版:

进行数据库的连接
  public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.添加jar
        //2.加载驱动
        Class.forName("com.mysql.jdbc.Driver");//初始化给定的类
        //3.通过驱动管理器获取连接对象
        //url是为了防止数据库和代码不在同一台机器    jdbc:mysql:// 是固定的  localhost 本地  ip地址  不同  java:你的数据库名称
        String url = "jdbc:mysql://localhost:3306/java";
        String user = "root";
        String pwd = "123456";
        Connection connection = DriverManager.getConnection(url, user, pwd);
        System.out.println("connection = " + connection);
    }

进行插入数据:编写的sql语句?作为占位符 ,建立预处理命令对象后进行参数的填空,最后执行executeUpdate()操作(参数已填充完毕),最后释放资源。

 public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.通过驱动管理器获取连接对象  Url表示和数据库通信的地址 如果url中需要带参数,则需要使用?进行连接  如果需要使用多个参数,从第二个参数开始使用&
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8", "root", "123456");
        //3.编写sql语句   ?作为占位符
        String sql = "insert into fruitdb values(0,?,?,?,?)";
        //4.创建预处理命令对象  PreparedStatement(是接口) 把 sql语句装进去然后给DB
        PreparedStatement psmt = connection.prepareStatement(sql);
        //5.填充参数  1234 为第几个问号
        psmt.setString(1,"banana");
        psmt.setInt(2,15);
        psmt.setInt(3,100);
        psmt.setString(4,"very delicious");
        //6.执行更新(增删改),返回影响行数
        int count = psmt.executeUpdate();
        System.out.println(count>0?"添加成功":"添加失败!");
        //7.释放资源(关闭连接,先关闭psmt,后关闭con)
        psmt.close();
        connection.close();

    }

修与改:除了sql语句不同外,其他的和插入步骤全部一致,返回值也一致

  public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Fruit fruit = new Fruit(4,"grapy",15,30);
        Class.forName("com.mysql.jdbc.Driver");
        //2.通过驱动管理器获取连接对象  Url表示和数据库通信的地址 如果url中需要带参数,则需要使用?进行连接  如果需要使用多个参数,从第二个参数开始使用&
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8", "root", "123xwt");
        //3.编写sql语句   ?作为占位符
        String sql = "update fruitdb set fname = ?,price=?,fcount = ? where fid = ?";
        //String sql = "delete from  fruitdb where fid = ?";
        PreparedStatement psmt = connection.prepareStatement(sql);
        psmt.setString(1,fruit.getFname());
        psmt.setInt(2,fruit.getPrice());
        psmt.setInt(3,fruit.getFcount());
        psmt.setInt(4,fruit.getFid());
        int count = psmt.executeUpdate();
        System.out.println(count>0?"添加成功":"添加失败!");
        psmt.close();
        connection.close();
    }

查询操作:返回的是结果集ResultSet,同时需要遍历使用get,数字代表列号(从1开始),字符串代表结果集的列名(SQL语句中是别名用别名),执行的是.executeQuery(),释放资源时,结果集也要释放。

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.通过驱动管理器获取连接对象  Url表示和数据库通信的地址 如果url中需要带参数,则需要使用?进行连接  如果需要使用多个参数,从第二个参数开始使用&
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8", "root", "123xwt");
        //3.编写sql语句   ?作为占位符
        String sql = "select * from fruitdb ";
        //4.创建预处理命令对象  PreparedStatement(是接口) 把 sql语句装进去然后给DB
        PreparedStatement psmt = connection.prepareStatement(sql);
        //5.执行查询,返回结果集
        ResultSet rs = psmt.executeQuery();

        ArrayList<Fruit> fruitArrayList = new ArrayList<>();
        //6,解析结果集
        while (rs.next()){
            int fid = rs.getInt(1);//1表示当前行的第一列
            String fname = rs.getString("fname");//getString/getInt 可以接结果集的列名(SQL语句中是别名用别名)
            int price = rs.getInt(3);
            int fcount = rs.getInt(4);
            String fremark = rs.getString("remark");
            Fruit fruit = new Fruit(fid, fname, price, fcount, fremark);
            fruitArrayList.add(fruit);
        }

        //7.释放资源(关闭连接,先关闭psmt,后关闭con)
        rs.close();//结果集也需要关闭
        psmt.close();
        connection.close();
        fruitArrayList.forEach(System.out::println );
    }

直接上DAO:
先写一个Dao相关的接口
public interface FruitDao {
    //查询库存列表
    List<Fruit> getFruitList();

    //新增库存
    boolean addFruit(Fruit fruit);
    //修改库存
    boolean updateFruit(Fruit fruit);

    //根据名称查询特定库存
    Fruit getFruitByFname(String fname);
    //删除特定库存记录
    boolean delFruit(String fname);
}

 实现类实现接口:

public class FruitDaoImpl extends BaseDao<Fruit> implements FruitDao {

    @Override
    public List<Fruit> getFruitList() {
        String sql = "select * from fruitdb ";
        return super.executeQuery(sql);
    }

    @Override
    public boolean addFruit(Fruit fruit) {
        String sql = "insert into fruitdb values(0,?,?,?,?)";
        return super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark())>0;
    }

    @Override
    public boolean updateFruit(Fruit fruit) {
        String sql = "update fruitdb set fcount = ? where fid = ?";

        return super.executeUpdate(sql,fruit.getFcount(),fruit.getFid())>0;
    }
    @Override
    public Fruit getFruitByFname(String fname) {
        String sql = "select * from fruitdb where fname= ?";
        return super.load(sql,fname);
    }

    @Override
    public boolean delFruit(String fname) {
        String sql = "delete from fruitdb where fname like ?";
        return super.executeUpdate(sql,fname)>0;
    }
}

将所有的操作写在父类方法里,实现类继承,然后传入相关sql语句,调用相关方法

public abstract class BaseDao<T> {
    protected ResultSet rs;
    protected PreparedStatement psmt;
    protected Connection connection;
    protected String URL= "jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8";
    protected String DRIVER= "com.mysql.jdbc.Driver";
    protected String USER = "root";
    protected String PWD = "123xwt";
    //T的class对象
    private Class entityClass;
    public BaseDao(){
        //获得父类的泛型类(com...父类名<泛型类型>
        Type genericSuperclass = getClass().getGenericSuperclass();
        //ParameterizedType 参数化类型,即泛型   getActualTypeArguments()过的参数化类型的数组,泛型可能有多个
        Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
        //获取到的<T>的真实的类型
        Type actualType = actualTypeArguments[0];
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    protected Connection getCon(){
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PWD);
            return connection;

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //执行更新,返回影响行数   Object... params    不定长参数,可传入多个参数
    protected int executeUpdate(String sql,Object... params){
        boolean insertFlag = false;//为了获取自增列
        //trim() 去除首尾空格  toUpperCase() 全部转换为大写  startsWith() 以什么开头
        insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
        try {
            connection = getCon();
            if (insertFlag){
                psmt = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            } else {
                psmt = connection.prepareStatement(sql);
            }
            setParams(psmt,params);
            int count = psmt.executeUpdate();

            rs = psmt.getGeneratedKeys();//insert 语句才会这样执行
            if (rs.next()){
                return ((Long)rs.getLong(1)).intValue();  //返回自增列值
            }
            return count;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if (psmt!=null){
                    psmt.close();
                }
                if (connection!=null&&!connection.isClosed()){
                    connection.close();
                }}
            catch(SQLException e){
                e.printStackTrace();
            }
        }
    return 0;}
    //给预处理命令对象设置参数
    private void setParams(PreparedStatement psmt,Object... params) throws SQLException {
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i + 1, params[i]);
            }
        }
    }
    //通过反射技术给obj对象的property属性赋propertyvalue值
    private void setValue(Object obj,String property,Object propertyValue){
        Class clazz = obj.getClass();
        try {
            //获取property这个字符串对应的属性名﹐比如"fid"去找 obj对象中的 fid属性
            Field field = clazz.getDeclaredField(property);
            if (field!=null){
                field.setAccessible(true);//强制访问,防止是private
                field.set(obj,propertyValue);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
    //执行查询,返回查询结果集
    protected ArrayList<T> executeQuery(String sql,Object... params){
        ArrayList<T> arrayList = new ArrayList<>();
        try {
            connection = getCon();
            psmt = connection.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据︰描迹结果集数据的数据,简单讲,就是这个结果集有哪些列,什么类型等等
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            while (rs.next()){
                T entity = (T) entityClass.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    String columnName = rsmd.getColumnName(i + 1);//获取列名
                    Object columnValue = rs.getObject(i + 1); //获取值
                    setValue(entity,columnName,columnValue);
                };
                //Fruit fruit = new Fruit(fid, fname, price, fcount, fremark);
                arrayList.add(entity);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            try {
                if (psmt!=null){
                    psmt.close();
                }
                if (connection!=null&&!connection.isClosed()){
                    connection.close();
                }}
            catch(SQLException e){
                e.printStackTrace();
            }
        }
        return arrayList;

    }
    //执行查询,返回单个实体对象
    protected T load(String sql,Object... params){
        try {
            connection = getCon();
            psmt = connection.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据︰描迹结果集数据的数据,简单讲,就是这个结果集有哪些列,什么类型等等
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            if (rs.next()){
                T entity = (T) entityClass.newInstance();//新建一个实例
                for (int i = 0; i < columnCount; i++) {
                    String columnName = rsmd.getColumnName(i + 1);//获取列名
                    Object columnValue = rs.getObject(i + 1); //获取值
                    setValue(entity,columnName,columnValue);
                }
                return entity;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            try {
                if (psmt!=null){
                    psmt.close();
                }
                if (connection!=null&&!connection.isClosed()){
                    connection.close();
                }}
            catch(SQLException e){
                e.printStackTrace();
            }
        }
        return null;
    }
    //执行复杂查询(聚合函数等) 返回统计结果
    protected Object[] executeComplexQuer(String sql,Object... params){
        try {
            connection = getCon();
            psmt = connection.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据︰描迹结果集数据的数据,简单讲,就是这个结果集有哪些列,什么类型等等
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            if (rs.next()){
                for (int i = 0; i < columnCount; i++) {
                    Object columnValue = rs.getObject(i + 1); //获取值
                    columnValueArr[i] = columnValue;
                }
                return columnValueArr;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (psmt!=null){
                    psmt.close();
                }
                if (connection!=null&&!connection.isClosed()){
                    connection.close();
                }}
            catch(SQLException e){
                e.printStackTrace();
            }
        }
        return null;
    }
}

        我们把连接和释放写入一个方法里:

    protected Connection getCon(){
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PWD);
            return connection;

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

        当使用泛型时(可能时多个泛型),我们获取具体的类名  actualTypeArguments[0]获取第一个泛型的类名

public BaseDao(){
        //获得父类的泛型类(com...父类名<泛型类型>
        Type genericSuperclass = getClass().getGenericSuperclass();
        //ParameterizedType 参数化类型,即泛型   getActualTypeArguments()过的参数化类型的数组,泛型可能有多个
        Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
        //获取到的<T>的真实的类型
        Type actualType = actualTypeArguments[0];
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

        同时将预处理命令对象设置参数抽成一个方法:这里就是setObject

 //给预处理命令对象设置参数
    private void setParams(PreparedStatement psmt,Object... params) throws SQLException {
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i + 1, params[i]);
            }
        }
    }

        进行自增列查询时:预处理命令对象的创建需要使用额外的参数        Statement.RETURN_GENERATED_KEYS

psmt = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);

        同时获取时:

rs = psmt.getGeneratedKeys();//insert 语句才会这样执行
if (rs.next()){
    return ((Long)rs.getLong(1)).intValue();  //返回自增列值
}

进行批处理:要执行批处理任务,需要添加一个参数:rewriteBatchedStatements=true

同时使用.addBatch(); 和executeBatch();   当任务太多时,我们可以分批执行 用if

 

public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        //2.通过驱动管理器获取连接对象   如果要执行批处理任务,需要添加一个参数:rewriteBatchedStatements=true
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true", "root", "123xwt");
        //3.编写sql语句   ?作为占位符
        String sql = "insert into fruitdb values(0,?,?,?,?)";
        //4.创建预处理命令对象  PreparedStatement(是接口) 把 sql语句装进去然后给DB
        PreparedStatement psmt = connection.prepareStatement(sql);
        for (int i = 0; i <10 ; i++) {
            psmt.setString(1,"banana"+i);
            psmt.setInt(2,15);
            psmt.setInt(3,100);
            psmt.setString(4,"very delicious");
            //添加到批中
            psmt.addBatch();
            if (i%1000==0){//如果任务较多,可以分批次执行,每次执行完,清空任务队列
                psmt.executeBatch();
                psmt.clearBatch();
            }
        }
        int[] count = psmt.executeBatch();
        for (int i = 0; i < count.length; i++) {
            System.out.println(count[i]);
        }
        //7.释放资源(关闭连接,先关闭psmt,后关闭con)
        psmt.close();
        connection.close();

    }

使用德鲁伊Druid连接池

//1.连接池中被close的对象并没有被真正关闭,而是将状态设置为空闲状态,然后放回池子,下次获取连接对象,这个对象会被重复利用
//2.没有被close的连接对象会被一直占用,那么下次继续获取连接对象,是不会获取到这个对象的
//读取外部的配置文件
public class Demo05Druid {
    public static void main(String[] args) throws Exception {

        Properties properties = new Properties();
        InputStream is = Demo05Druid.class.getClassLoader().getResourceAsStream("jdbc2.properties");
        properties.load(is);//加载属性文件

        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        //1.连接池中被close的对象并没有被真正关闭,而是将状态设置为空闲状态,然后放回池子,下次获取连接对象,这个对象会被重复利用
        //2.没有被close的连接对象会被一直占用,那么下次继续获取连接对象,是不会获取到这个对象的
        Connection connection = dataSource.getConnection();//建立连接对象,可以建立多个连接对象
        System.out.println(connection);
    }
}

创建属性配置文件,写入参数:

driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/java?userSSL=false&useUnicode=true&characterEncoding=utf-8
username = root
password = 123456
initialSize = 2
maxActive = 5
maxWait = 5000

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值