2-28 数据库链接操作_JDBC_02

JDBC操作之DML

需求:向t_student表中 【插入,修改和删除数据】

步骤1: 加载注册驱动【com.mysql.jdbc.Driver】–》【可以不写,但是习惯问题】

步骤2:获取链接数据库对象Connection --》 DriverManager来获取连接对象

步骤3:编写静态SQL语句–》 【一次性写好SQL并且参数已经确定】—》写成字符串,但是语句中不用分号

步骤4:创建可以执行和发送静态语句的对象Statement --》通过连接对象Connection创建

步骤5:发送语句和执行executeUpdate方法将静态语句进行发送和执行

PS: 这个语句可以执行DDL 和 DML 操作,如果是DML操作会返回一个值,这个值是一个整数,是受影响操作的行数,可以同判断这个数确定是否操作成功【只要大于0即可】

PS: 执行建表语句的时候,返回值是0但是代表建表成功

步骤6:数据库属于长连接,这个资源只要不释放,就会一直保持连接

PS:释放原则:1.程序执行完毕关闭【Demo级别可以】 2.手动释放资源,有一个统一的操作close

插入一条数据到数据库表中

insert into t_student(name,age)values('乔峰',33)

编写代码

package com.qfedu.JDBC.DML;

import java.sql.*;

/**
 * 通过JDBC向表中插入数据
 */
public class InsertTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库链接对象
        //loaclhost -->代表着两个地址 一个是内环地址【计算自己自带 127.0.0.1】  一个是外环地址【根据网线或路由器分配得来】
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
        //3.创建执行和发送静态SQL语句的对象
        Statement statement = conn.createStatement();
        //4.编写静态SQL语句
        String sql = "insert into t_student(name,age)values('乔峰',33)";
        //5.执行发送操作
        int i = statement.executeUpdate(sql);
        if(i > 0) {
            System.out.println("插入成功");
        }else {
            System.out.println("插入失败,执行语句问题");
        }
        //6.释放资源
        statement.close();
        conn.close();


    }
}


需求:

 1. 在插入一条值   啊朱,18
    2. 更新数据将乔峰,修改为 萧峰,年龄修改为34

3.将啊朱数据进行删除

package com.qfedu.JDBC.DML;

public class InsertAndUpdateAndDeleteSQL {
     private InsertAndUpdateAndDeleteSQL(){};
     //提供插入语句【静态SQL】
    public static final String INSERT_SQL = "insert into t_student(name,age)values('啊朱',18)";
     //提供更新语句
     public static final String UPDATE_SQL = "update t_student set name = '萧峰',age = 34 where id = 1";
    //删除语句
    public static final String DELETE_SQL = "delete from t_student where name = '啊朱'";


}


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

/**
 * 需求:
 *
 *    1. 在插入一条值   啊朱,18
 *    2. 更新数据将乔峰,修改为 萧峰,年龄修改为34
 *    3.将啊朱数据进行删除
 */
public class UpdateAndDelete {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        /*
         JDBC连接驱动路径写法:
         1.常规
         jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称

         2.可以在数据库名称后面添加连接数据
         【如果直接和数据库名称相连使用? 剩余的数据库参数使用&符号进行连接】
          连接数据库的同时指定数据库的编码集
          jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useUnicode=true&characterEncoding=UTF-8

         3.MySQL 5.6版本开始之后,使用JDBC连接数据库时,数据库连接会对SSL连接进行安全验证
         PS:连接数据库的时候回出现一行警告,这个警告不会影响数据库执行
             如果出现了这个警告,关闭警告即可
              jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useSSL=false

           ps:习惯性这样书写数据库链接语句
    jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useUnicode=true&characterEncoding=UTF-8&useSSL=false
         */
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123456");
        Statement statement = connection.createStatement();

        //1.执行插入
        //InsertTableData(statement);

        //2.更新
        //atl+ctrl+m --> 快捷抽取方法
        //UpdateTableData(statement);

        //3.删除
        //DeleteTableData(statement);
        
        statement.close();
        connection.close();
    }

    public static void DeleteTableData(Statement statement) throws SQLException {
        int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.DELETE_SQL);
        if (i>0){
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
    }

    public static void UpdateTableData(Statement statement) throws SQLException {
        int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.UPDATE_SQL);
        if (i>0){
            System.out.println("更新成功");
        }else{
            System.out.println("更新失败");
        }
    }

    public static void InsertTableData(Statement statement) throws SQLException {
        int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.INSERT_SQL);
        if (i>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }
    }
}

总结:

想通过JDBC对数据库进行增删改操作,就需要使用到一个语句对象Statement【这个对象只接受静态SQL语句】

使用executeUpdate方法进行操作,返回值是一个int类型数据,通过判断这个数据是否大于0即可知道是否添加成功【创建表返回时0,但是操作成功】,DDL和DML都需要和这个方法执行

JDBC操作DQL

DQL语句这里依旧是使用静态SQL语句,还是需要是Statement对象,DQL语句在通过JDBC操作的时候使用方法和得到返回这都有很大改变

返回值类型方法和方法说明
ResultSetexecuteQuery(String sql) 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。

什么ResultSet?

ResultSet表示数据库结果集的数据表,通常通过执行查询数据库的语句【DQL】生成。

通过对对这个虚拟表的操作即可以取出当前虚拟表中的值

PS: 这里大家要记住在学习MySQL时MySQL数据类型对应Java中的数据类型什么

演示代码

package com.qfedu.JDBC.DQL;


import java.sql.*;

/**
 * DQL语句通过JDBC进行操作
 */
public class SelectTest {
    public static void main(String[] args) throws Exception {
        String sql = "select * from t_student";
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
        Statement statement = connection.createStatement();
        //resultSet就是存储这个查询语句得到虚拟表对象
        ResultSet resultSet = statement.executeQuery(sql);
        System.out.println(resultSet);
        //问题:此时返回resultSet确实是一个虚拟表对象com.mysql.jdbc.JDBC4ResultSet@67424e82,所以如何获取其内部值
        //在ResultSet官方API中有一句说明,ResultSet存在着一个光标,通过移动这个光标即可以获取到resultSet对象中存值
        //ResultSet中提供一个方法 next -->移动光标,如果有下一行数据返回true,否则没有数据则返回false
        //利用这个原则,就可以使用while循环,循环获取出结果集中数据了
        while(resultSet.next()){//移动光标获取值
            //如果需要回去到具体一行数据值,ResultSet提供了两个方法
            /*
            ps:以下的XXX代表的是不同数据类型,通过get方法表中获取数据的数据类型
            1.    XXXX  getXXXX(int  columnIndex)
                  获取当前光标行的第N列数据【根据表从左向后获取列,左第一列为为1,依次类推】
                  例如: student表中有三个列  id【1】   name【2】  age【3】
                       通过当前get方法获取列数据时      getInt(1) --> 相当于获取到 id着列的值

            2.   XXXX  getXXXX(String columnName)
                  获取当前光标行的列的名字获取列中存储数据
                  例如: student表中有三个列  id   name  age
                       通过当前get方法获取列数据时      getInt(id) --> 相当于获取到 id着列的值
             */
            //获取ResultSet对象中存储数据值是一定要注意使用是什么数据类型【☞表中】,接收的时候使用什么数据类型接收【☞Java代码中】
            //这两个数据类型一定要一一对应
            int id = resultSet.getInt(1);
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            System.out.println("存储在Student表中 ID值是:"+id+" name值是:"+name+" age值是:"+age);
        }
        //ResultSet也属于长连接对象,所以也要释放
        resultSet.close();
        statement.close();
        connection.close();
    }
}

ResultSet执行过程

1.在没有调用next方法之前,光标是在列这一行

请添加图片描述

2.代用了next方法,光标会移动到一行数据的位置

请添加图片描述

3.通过getXXX方法获取出这一行数据

4.再次调用next方法,结果没有数据了,返回false 程序结束

请添加图片描述

需求:统计出t_student中有多少条数据

package com.qfedu.JDBC.DQL;


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

/**
 * DQL语句通过JDBC进行操作[统计数据]
 */
public class SelectTest2 {
    public static void main(String[] args) throws Exception {
        String sql = "select count(id) count from t_student";
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
        Statement statement = connection.createStatement();
        //resultSet就是存储这个查询语句得到虚拟表对象
        ResultSet resultSet = statement.executeQuery(sql);

        while(resultSet.next()) {
            //直接传递列名
            int count1 = resultSet.getInt("count");
            System.out.println(count1);
            //如果要是你确定列个数
            int count2 = resultSet.getInt(1);
            System.out.println(count2);
        }

        resultSet.close();
        statement.close();
        connection.close();
    }
}

使用JDBC实现登录案例

1.实现登录

  • 创建一张用户表 User
    • id ,主键、自动增长。
    • 用户名,字符串类型,唯一、非空
    • 密码,字符串类型,非空
    • 手机号码,字符串类型
  • 插入 2 条测试语句
  • 通过控制台用户输入用户名和密码。
  • 用户输入的用户名和密码作为条件,编写查询 SQL 语句。
  • 如果该用户存在,提示登录成功,反之提示失败。

代码

package com.qfedu.JDBC.LogIn;
//提供静态SQL语句
public class CreateAndInsertSQL{
    private CreateAndInsertSQL(){};
    //提供建表
    public static  final  String CREATE_TABLE =
            "create table user(" +
                    "id int primary key auto_increment," +
                    "username varchar(20) unique not null," +
                    "password varchar(20) not null," +
                    "phoneNumber varchar(20)" +
                    ")";
    //提供插入语句
    public  static final String INSERTINOT_1 =
            "insert into user(username,password,phoneNumber)values('zhangsan','123456','13112345678')";
    public  static final String INSERTINOT_2 =
            "insert into user(username,password,phoneNumber)values('lisi','111111','13842383838')";

    public static String  SelectTableData(String username,String password){
        return "select * from user where username = '"+username+"' and password = '"+ password+"'";
    }


}
package com.qfedu.JDBC.LogIn;

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

//创建表和插入表中数据
public class CreateTableAndInsert{
    public static void main(String[] args) throws Exception {
            //加载连接驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
        //创建执行SQL语句对象【静态语句】
        Statement statement = connection.createStatement();
        //5.建表
        int succeed = statement.executeUpdate(CreateAndInsertSQL.CREATE_TABLE);
        if (succeed == 0){
            System.out.println("建表成功");
        }
        int i = statement.executeUpdate(CreateAndInsertSQL.INSERTINOT_1);
        int i1 = statement.executeUpdate(CreateAndInsertSQL.INSERTINOT_2);
        if(i>0 && i1 >0){
            System.out.println("插入数据成功");
        }
        statement.close();
        connection.close();
    }

}
package com.qfedu.JDBC.LogIn;

import java.sql.*;
import java.util.Scanner;

public class LoginTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = input.nextLine();
        System.out.println("请输入密码:");
        String password = input.nextLine();

        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(CreateAndInsertSQL.SelectTableData(username, password));
        //如果判断是否登录成功
         if(resultSet.next()){
             System.out.println("登录成功");
         }else{
             System.out.println("登录失败");
         }
         resultSet.close();
         statement.close();
         connection.close();


    }
}

预编译语句对象和JDBC工具抽取封装

预编译语句对象

在之前所有编写MySQL语句的时候,我们都是在开发阶段就要直接将SQL语句写好,并且里面的传输数据也是直接写死,对于这样SQL语句称为【静态SQL语句】,这样静态SQL语句存在一些弊端

【1.不好修改 2.语句中参数是写死的,不能动态获取参数

**3.静态语句没有进行优化 	4.静态语句及其容易出现SQL注入】**

Java为了解决这些问题,它提供了一个Statement子类【子接口】,叫做PreparedStatement,它也是一个接口,它提供了一个静态编译语句对象

PreparedStatement表示预编译的 SQL 语句的对象。

SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

在使用预编译语句对象到时候,需要使用到占位符号,进行参数占位 --》 【?】

例如:

静态语句向表中插入数据

insert into t_student(name,age)values('zhangsan',18);

预编译语句性表中插入数据

 insert into t_student(name,age)values(?,?);

在语句中【?】只是一个占位符号,没有具体值,所以预编译语句提供一个方法可以对【?】进行赋值操作

void setXXXX(int parameterIndex, XXXX value);

PS:XXX代表传入数据库中数据的数据类型
位置计算,从左向右,占位符的第一位位置是【1】,依次类推

预编译语句和静态语句对比

预编译语句特点:

1.代码的可读性和可维护性比较【因为使用占位,只需要实现一个语句,动态改变值就可以不停查询出不同结果】

ps:所以预编译语句类似于【语句模板】

2.预编译语句可以最大能力提高性能

3.预防SQL注入

SQL语句的执行流程

请添加图片描述

修改一个案例实现预编译语句

需求:使用预编译语句向t_student插入数据
    package com.qfedu.JDBC.PreparedStatement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

//实现预编译语句
public class PreparedStatementDemo {
    public static void main(String[] args)throws Exception {
        //1.写预编译语句
        String  preSQL = "insert into t_student(name,age)values(?,?)";
        //加载连接驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");

        //创建预编译语句对象--》需要传入预编译语句对象进行对象创建
        PreparedStatement preparedStatement = connection.prepareStatement(preSQL);

        //对象创建完毕之后,语句中还是存在占位符号,所以需要使用预编译语句对象对当前占位符进行赋值
        //1.先对预编译语句对象中占位进行赋值
        preparedStatement.setString(1,"西方失败");//第一个?赋值
        preparedStatement.setInt(2,1);//第二个?赋值

        //执行DDL或DML语句,方法依旧是 executeUpdate 这个没有参数直接执行并接收返回值【还是判断是否大于0】
        int i = preparedStatement.executeUpdate();
        //boolean execute = preparedStatement.execute();
        if (i>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }
        //预编译语句对象也属于长连接
        preparedStatement.close();
        connection.close();


    }
}


需求:使用预编译语句进行查询
package com.qfedu.JDBC.PreparedStatement;

import jdk.nashorn.internal.ir.CallNode;
import netscape.javascript.JSUtil;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

//实现预编译语句
public class PreparedStatementDemo2 {
    public static void main(String[] args)throws Exception {
        //1.写预编译语句
        String  preSQL = "select * from t_student where id = ?";
        //加载连接驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");

        //创建预编译语句对象--》需要传入预编译语句对象进行对象创建
        PreparedStatement preparedStatement = connection.prepareStatement(preSQL);

        //对象创建完毕之后,语句中还是存在占位符号,所以需要使用预编译语句对象对当前占位符进行赋值
        //1.先对预编译语句对象中占位进行赋值
        preparedStatement.setInt(1,4);

        //2.使用DQL语言进行查询 executeQuery方法,这个方法没有参数
        ResultSet resultSet = preparedStatement.executeQuery();
        boolean execute = preparedStatement.execute();
        System.out.println(execute);
        while(resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            System.out.println(id+name+age);
        }
        //预编译语句对象也属于长连接
        preparedStatement.close();
        connection.close();


    }
}


ps:预编译语句中提供一个execute方法,这个方法返回值是boolean,即可以运行DDL和DML,也可以运行DQL,但是这个方法的返回值决定点在于是否可以获取到一个ResultSet对象,也就是说execute方法对查询语句的到ResultSet结果集之后会返回【true】,剩余DDL和DML返回值为【false】

综上所述:

1.对于预编译语句而言,可以依旧使用executeUpdate执行【DDL和DML】语句,也可以使用executeQuery执行【DQL】语句,这两个方法对比静态语句中方法少了方法形参,但是执行效果是一样的

模拟SQL注入

package com.qfedu.JDBC.PreparedStatement;

import java.sql.*;

/**
 * SQL注入操作
 */
public class LoginTest {
    public static void main(String[] args) throws Exception {
        //用户注册信息user表,只有用户名和密码正取之后才能让其登录
        //1.静态SQL语句
        String  staticSQL = "select * from user where username = '' OR 1 = 1 AND password = '123456'";
        String  perSQL = "select * from user where username = ? AND password = ?";
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123456");
//        Statement statement = connection.createStatement();
//        ResultSet resultSet = statement.executeQuery(staticSQL);
//        if(resultSet.next()){
//            System.out.println("登录成功");
//        }else{
//            System.out.println("登录失败");
//        }
        PreparedStatement preparedStatement = connection.prepareStatement(perSQL);
        //因为数据是以占位符的形式传递进去
        //因为预编译语句会将参数看做是一个字段【列】一个值 而不是当做一个SQL语句运行
        /*
        说明:
         静态SQL中,它会将where子句的后面看做时一个表达式 和整个整个语句融为一体,是一个完整的SQL
         预编译语句,他会将出现占位符号的位置,看做就是一个字段【列】的值
         ps:将 '' OR 1 = 1 看做是一个用户名即 username列里面是否存在和这个值
         */
        preparedStatement.setString(1,"'' OR 1 = 1");



    }
}

核心:"为了SQL语句的安全建议开发的时候都写预编译语句"


JDBC封装工具类

在实际开发JDBC的过程中,存在大量向同的重复性代码【触发了DRY原则】,所以我们需要对重复的代码进行抽取,封装到一个统一的类中,通过这类就可以获取到JDBC的基础操作,就不用大量重复编写代码

请添加图片描述

通过对之前代码的简单分析可以的到一些结论

1.加载注册驱动每个对象都需要使用

2.获取连接对象

在获取连接对象的时候用,需要传递参数,如果将参数写死在代码中,如果修改连接数据库,那么你就要查找对应代码才能修改,还是需要修改原码,所以建议将当前数据封装到一个文件中,读取这个文件即可以获取到链接的数据,以后要修改连接的时候,无需查找代码,只需要文件即可

  1. 数据库的连接属于一个【长连接】,程序不关闭的且没有做任何资源释放,后果就是一直会有一个连接资源占用,如果是Demo级别,其实没有大问题,但是在实际开发中10万人连接,服务器的内存压力就非常大,甚至会出现崩溃【宕机】

抽取一个工具类【DBUtil】这个工具类中就提供以上三种操作,后续需要什么在向这个类添加即可

步骤1:创建一个资源文件,将会数据库连接参数写入到文件中,使用时读取文件即可

#数据库连接配置写到这个文件中
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1
username=root
password=123456

步骤2:抽取创建DBUtil工具类

package com.qfedu.JDBC.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类
 */
public class DBUtil {
    //1.工具类不会创建对象,所以将构造方法私有化
    private  DBUtil(){}
    //2.创建一个Properties文件对象以便读取文件中的数据
    private static final Properties p = new Properties();
    //3.提供一个静态代码块 用来对要使用数据库连接对象进行配置
    static {
        //3.1先文件中内容读取出来
        try {
            //获取类的类的加载器
            ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            //通过类的加载器获取classPath路径下文件【db.properties】
            InputStream resourceAsStream = contextClassLoader.getResourceAsStream("db.properties");
            p.load(resourceAsStream);//通过字节流加载
        } catch (IOException e) {
            throw  new  RuntimeException("加载classPath路径下的db.properties文件出现失败:"+e.getMessage());
        }
        //3.2 加载注册驱动
        try {
            Class.forName(p.getProperty("driver"));
        } catch (ClassNotFoundException e) {
            throw  new  RuntimeException("数据库驱动加载失败:"+e.getMessage());
        }
    }

    /**
     * 获取Connection连接对象
     * @return Connection连接对象
     *         会抛出异常,连接对象获取失败
     */
    public static Connection getConnectionInstance(){
        try {
            return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
        } catch (SQLException e) {
            throw  new  RuntimeException("数据库获取连接对象失败:"+e.getMessage());
        }

    }

    /**
     * 释放JDBC连接资源对象
     * @param connection 连接对象
     * @param statement  静态SQL语句对象
     * @param preparedStatement  预编译语句对象
     * @param resultSet  结果集
     */
    public static void closeAll(Connection connection, Statement statement, PreparedStatement preparedStatement, ResultSet resultSet){
        //这里的释放原则,只要创建就是释放 反之不执行
        try {
            if (connection != null) {
                connection.close();
            }
            if (statement != null) {
                statement.close();
            }
            if(preparedStatement != null){
                preparedStatement.close();
            }
            if(resultSet != null){
                resultSet.close();
            }
        }catch (SQLException e){
            throw  new  RuntimeException("释放资源出出现失败:"+e.getMessage());

        }
    }


}


步骤3:测试工具类

package com.qfedu.JDBC.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBTest {
    public static void main(String[] args) throws SQLException {
        //查询语句
        String sql = "select * from t_student where id = ?";
        //1.加载驱动获取连接对象
        Connection connection = DBUtil.getConnectionInstance();
        //2.获取预编译语句对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,3);
        ResultSet resultSet = preparedStatement.executeQuery();
        if(resultSet.next()){
            System.out.println("查询成功");
        }
        DBUtil.closeAll(connection,null,preparedStatement,resultSet);

    }
}


JDBC之ORM映射

ORM(object Relational Mapping)从数据库中查询出的结果集(ResultSet)在进行遍历是,我们逐行取出值,但是这个是零散,所以为了使用方便,在实际开发中提供了一种思想,更加便于管理这些零散数据,主要是提供了对零散数据的封装,提供公益的访问方式和使用途径

PS:关系型数据库和Java中的类是存在一定联系

​ 数据库中表 -----》 看做 -----》Java中类

​ 数据库中表的列 ----》 看做 ----》 Java中类中属性

​ 数据库中表的每一行数据 —》 看做 —》 java中类的对象

所以就是因为存在这种关系 —》称之为 【ORM映射】

因为要将这些零散进行封装,所以就需要提供一个存储零散数据载题,这个载体就叫做**【实体类】**

ps:什么是实体类?就是刚开始学习面向对象时的描述类

什么是实体类(entity)?

实体类的作用就是通过ResultSet查询出来的零散数据的统一载体

一行数据中,多个零散的数据进行整体的封装,通过entity的规则对表中数据进行对象的封装

实体类的设计原则?

【表名 == 类型】 【列 == 属性】 【实体类要提供get和set方法】 【提供有参无参构造方法】

扩展: JavaBean规范

ps:实体类就是JavaBean

JavaBean是一种Java语言的一个重要的组件【就是一个类】

要写和这个JavaBean这类就需要遵守一个规范

1.这个类必须使用public修饰

2.必须保证有【有参无参构造反方】

3.包含处理属性操作的手段【提供get和set】

JavaBean规范类一般多用于domain、dao、services组件中分装类【存储数据使用】

实例类案例

package com.qfedu.JDBC.entity;
//这类就是tbStock这个表的实体类
public class T_tbStock {

    //跟表中列的名一致【属性名】
    private String ordername;
    private String locationid;
    private String dateid;

    //这类提供get和Set 还有有参无参构造方法

    public T_tbStock() {
    }

    public T_tbStock(String ordername, String locationid, String dateid) {
        this.ordername = ordername;
        this.locationid = locationid;
        this.dateid = dateid;
    }

    public String getOrdername() {
        return ordername;
    }

    public void setOrdername(String ordername) {
        this.ordername = ordername;
    }

    public String getLocationid() {
        return locationid;
    }

    public void setLocationid(String locationid) {
        this.locationid = locationid;
    }

    public String getDateid() {
        return dateid;
    }

    public void setDateid(String dateid) {
        this.dateid = dateid;
    }

    @Override
    public String toString() {
        return "T_tbStock{" +
                "ordername='" + ordername + '\'' +
                ", locationid='" + locationid + '\'' +
                ", dateid='" + dateid + '\'' +
                '}';
    }
}
package com.qfedu.JDBC.entity;

import com.qfedu.JDBC.util.DBUtil;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/*
实体类使用
 */
public class T_tbStockTest {
    public static void main(String[] args) throws Exception {
        //1.需要加载注册驱动和创建连接对象
        Connection connection = DBUtil.getConnectionInstance();
        String sql = "select * from tbstock";
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        //如果按照以前的方式
//        while(resultSet.next()){
//            //零散数据的体现其实就是这个表中值,我们无法提供合理方式进行存
//            String ordername = resultSet.getString(1);
//            String locationid = resultSet.getString(2);
//            String dateid = resultSet.getString(3);
//        }
        //以表和类之间产生一个映射关系【ORM】 表即是类 表中列即是类中属性 表中每一行数据封装在这个类的对象
        List<T_tbStock> list = new ArrayList<>();
       while(resultSet.next()){

            String ordername = resultSet.getString(1);
            String locationid = resultSet.getString(2);
            String dateid = resultSet.getString(3);
            //将数据分装进对象中
           T_tbStock tb = new T_tbStock(ordername,locationid,dateid);
           list.add(tb);
        }
       list.forEach(System.out::println);




    }
}


DAO数据访问对象(Data Access Object)

什么DAO:主要作用就是执行【CRUD(增删改查)】

DAO是一个数据访问接口,数据访问:顾名思义就是与数据库打交道

在核心JavaEE中是这样介绍DAO模式的:为了建立一个健壮的JavaEE的应用程序,应该将所有对数据库的访问抽象的封装在一个公共API中

用程序设计的语言来说,其实就是建议一个接口,接口中定了此应用程序中将会用到所有事务方法

在应用程序中,当需要和数据源进行交互的时候,则直接使用这个接口,并编写一个实现接口类,这个类中将实现接口所有的方法,并且对外提供暴露,外部只需要调用这个类就可以完成对数据库的操作,这个操作就是DAO包中核心

扩展 :DAO包中设计方式

DAO包的设计规范:

DAO包中组件:【DAO接口、DAO实现类、DAO的测试类】

分包的规范:

【以下仅以我开发经验而言】

com.公司的域名.项目名称.dao --> 存储着dao包中接口文件

com.公司的域名.项目名称.dao.impl --> 存储着Dao包中接口的实现类

com.公司的域名.项目名称.dao.domian --> 存放着Dao包中需要使用到实体类【ORM思想】

PS:有的的地方习惯将实体类单独抽取出来一个包entity,含义和domian是一样的

com.公司的域名.项目名称.dao.test --> 存测试文件

PS:在实际项目提交【甲方爸爸】,需要将test全员删除

​ JavaSE是以jar为打包,可以提供对外使用

​ JavaEE是以war为打包,可以提供对外使用

具体包所创建的东西

domain包:描述对象的,一般就是存储实体类 例如:Person.java

dao包: 接口文件【定义操作数据库的方法CRUD】 例如: IPersonDao 或 IPersonDAO

impl包: 这个包就是对dao中接口的具体实现类【CRUD】 例如:IPersonDAOImpl

test包: 测试包对impl包中实现类测试是否可以使用,能否争取完成操作 例如:PersonDAOTest

创建DAO包之后,我们需要使用面向接口编程:

所有触发DAO包的操作都需要使用接口来实现对象创建

例如: IPersonDAO pd = new IPersonDAOImpl();

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值