JavaWeb笔记之JavaWeb JDBC

news2024/9/28 9:26:22

//Author 流云

//Version 1.0
   

一. 引言

1.1 如何操作数据库
使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写 SQL 语句,点击执行,查看操作结果(结果集或受影响行数)。

   
1.2 实际开发中,不会采用数据库客户端操作
在实际开发中,当用户的数据发生改变时,不可能通过客户端操作执行 SQL 语句,因为操作量过大,无法保证效率和正确性。
    

二. JDBC

2.1 介绍
JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作。
     
2.2 核心思想
Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。

  
2.3 驱动包
mysql-connector-java-5.1.X 适用于 5.X 版本
mysql-connector-java-8.0.X 适用于 8.X版本
  
2.4 常用类
JDBC 是由多个接口和类进行功能实现。

    
2.5 环境搭建
在项目下新建 lib 文件夹,用于存放 jar 文件。
将 mysql 驱动mysql-connector-java-5.1.X复制到项目的 lib 文件夹中。
选中 lib 文件夹右键 Add as Libraay,点击 OK。
    

三. 开发步骤

3.1 注册驱动
使用 Class.forName("com.mysql.jdbc.Driver");手动加载字节码文件到 JVM 中。
Class.forName("com.mysql.jdbc.Driver");//加载驱动
  
3.2 连接数据库
通过 DriverManager.getConnection(url,user,password) 获取数据库连接对象。
        URL:jdbc:mysql://localhost:3306/database
        username:root
        password:1234
Connection conn = 
DriverManager.getConnection("jdbc:mysql://localhost:3306/database?
useUnicode=true&characterEncoding=utf8", "root","1234");
  
URL(Uniform Resource Locator) 统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成。
   
3.3 获取执行对象
通过 Connection 对象获得 Statement 对象,用于对数据库进行通用访问。
Statement statement = conn.createStatement();
  
3.4 执行SQL 语句
执行 SQL 语句并接收执行结果。
String sql ="INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)
VALUES('JAVA_Le','JAVA_Lecturer',4000,10000);";

int result = statement.executeUpdate(sql);//执行SQL语句并接收结果
   
注意:在编写 DML 语句时,一定要注意字符串参数的符号是单引号 '值'。
DML 语句:增删改时,返回受影响行数(int 类型)。
DQL 语句:查询时,返回结果数据(ResultSet 结果集)。
    
3.5 处理结果
接受处理操作结果。
if(result == 1){
    System.out.println("Success");
}
   
受影响行数:逻辑判断、方法返回。
查询结果集:迭代、依次获取。
  
3.6 释放资源
遵循先开后关原则,释放所使用到的资源对象。
statement.close();
conn.close();
   
3.7 综合案例
整合以上核心六步,实现向数据库表中插入一条数据。
package com.jdbc;

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

public class DeleteJdbc {
    public static void main(String[] args) throws Exception{
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb","root","1234");
        //3.获得执行SQL的对象
        Statement statement = connection.createStatement();
        //4.执行SQL语句,并接收结果
        int result = statement.executeUpdate("delete from t_jobs where job_id = 'H5_mgr';");
        //5.处理结果
        if(result==1){
            System.out.println("删除成功!");
        }else{
            System.out.println("删除失败!");
        }
        //6.释放资源
        statement.close();
        connection.close();
    }
}
  

四. ResultSet

在执行查询 SQL 后,存放查询到的结果集数据。
  
4.1 接收结果集
ResultSet rs = statement.executeQuery(sql);
ResultSet rs= statement.executeQuery("SELECT * FROM t_employees;");
  
4.2 遍历结果集
ResultSet 以表(table)结构进行临时结果的存储,需要通过 JDBC API 将其中数据进行依次获取。
        数据行指针:初始位置在第一行数据前,每调用一次 boolean next()方法ResultSet 的指针向下移动一行,结果为 true,表示当前行有数据。
        rs.getXxx(整数);代表根据列的编号顺序获得,从 1 开始。
        rs.getXxx("列名");代表根据列名获得。
boolean next() throws SQLException //判断 rs 结果集中下一行是否存在数据
  
4.2.1 遍历方法
int getInt(int columnIndex) throws SQLException //获得当前行第N列的int值
int getInt(String columnLabel) throws SQLException //获得当前行columnLabel列的int值

double getDouble(int columnIndex) throws SQLException //获得当前行第N列的double值
double getDouble(String columnLabel) throws SQLException //获得当前行columnLabel列的double值

String getString(int columnIndex) throws SQLException //获得当前行第N列的String值
String getString(String columnLabel) throws SQLException //获得当前行columnLabel列的String值

......
  
注意:列的编号从 1 开始。
  
4.3 综合案例
对 t_jobs 表中的所有数据进行遍历。
    
4.3.1 根据列名
package com.www.test;

import java.sql.*;

public class JobsQuery {
    public static void main(String[] args) {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/product", "root", "1234");
        //3.获取发送 sql 语句对象
        Statement statement = connection.createStatement();
        //4.执行 SQL 语句并接收结果集
        ResultSet resultSet = statement.executeQuery("select * from t_jobs");
        //5 处理结果集
        while(resultSet.next()){
            //5.1有数据,依据列名获取数据
            String job_id = resultSet.getString("job_id");
            String job_title = resultSet.getString("job_title");
            int min_salary = resultSet.getInt("min_salary");
            int max_salary = resultSet.getInt("max_salary");
            System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
        }
        //6.释放资源
        rs.close();
        statement.close();
        connection.close();
    }
}
    
4.3.2 根据编号
//。。。。与上无异
while(resultSet.next()){
    //5.2有数据,依据列名获取数据
    String job_id = resultSet.getString(1);
    String job_title = resultSet.getString(2);
    int min_salary = resultSet.getInt(3);
    int max_salary = resultSet.getInt(4);
    System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
}
//释放资源
  

五. 常见错误

java.lang.ClassNotFoundException:找不到类(类名书写错误、没有导入jar包)。
java.sql.SQLException:与sql语句相关的错误 (约束错误、表名列名书写错误) 建议:在客户端工具中测试SQL语句之后再粘贴在代码中。
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 原因:列值Sting类型没有加单引号。
Duplicate entry '1' for key 'PRIMARY' 原因,主键值已存在或混乱,更改主键值或清空表。
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'password' in 原因:可能输入的值的类型不对,确定是否插入的元素时对应的值的类型正确。
    

六. 登录案例

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

七. SQL注入

7.1 介绍
用户输入的数据中有 SQL 关键字或语法并且参与了 SQL 语句的编译,导致 SQL 语句编译后的条件含义为 true,一直得到正确的结果。这种现象称为 SQL 注入。
  
7.2 方案
由于编写的 SQL 语句是在用户输入数据,整合后再进行编译。所以为了避免 SQL 注入的问题,我们要使 SQL 语句在用户输入数据前就已进行编译成完整的 SQL 语句,再进行填充数据。
  

八. PreparedStatement

PreparedStatement 继承了 Statement 接口,执行 SQL 语句的方法无异。
  
8.1 应用
作用:
预编译SQL 语句,效率高。
安全,避免SQL注入 。
可以动态的填充数据,执行多个同构的 SQL 语句。
  
8.1.1 参数标记
//1.预编译 SQL 语句
PreparedStatement pstmt = conn.prepareStatement("select * from user where username=? and password=?");
  
注意:JDBC中的所有参数都由 ?符号占位,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。 
    
8.1.2 动态参数绑定
pstmt.setXxx(下标,值) 参数下标从 1 开始,为指定参数下标绑定值。
//1.预编译 SQL 语句
PreparedStatement pstmt = conn.prepareStatement("select * from user where username=? and password=?");

//2.为参数下标赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
  

九. 封装工具类

在实际JDBC的使用中,存在着大量的重复代码:例如连接数据库、关闭数据库等这些操作!
我们需要把传统的JDBC代码进行重构,抽取出通用的JDBC工具类!以后连接任何数据库、释放资源都可以使用这个工具类。

  
9.1 重用性方案
封装获取连接、释放资源两个方法。
        提供public static Connection getConnection(){}方法。
        提供public static void closeAll(Connection conn , Statement sm , ResultSet rs){}方法。
  
9.1.1 实现
package com.jdbc;

import java.sql.*;

/**
* 重用性方案
* 获取连接
* 释放资源
*/
 
public class DBUtils {
    static {//类加载,执行一次!
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //1.获取连接
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb", "root","1234");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    //2.释放资源
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  
9.2 跨平台方案
定义public static final Properties prop = new Properties(); //读取配置文件的Map。
定义static{
        //首次使用工具类时,加载驱动
InputStream is = JDBCUtil.class.getResourceAsStream("路径"); //通过复用本类自带流,读取jdbc.properties配置文件。classPath = bin
prop.load(is); //通过prop对象将流中的配置信息分割成键值对。
String driverName = prop.getProperty("driver"); //通过driverName的键获取对应的值(com.mysql.jdbc.Driver)
Class.forName(driverName); //加载驱动。
}
    
9.2.1 实现
在src 目录下新建 db.properties 文件。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb3
user=root
password=123456
    
工具类的封装。
package com.jdbc2;

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

public class DBUtils {
    private static final Properties PROPERTIES = new Properties();//存储配置文件的map
    static {
        InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
        try {
            PROPERTIES.load(is);//通过流,将配置文件内容加载到properties集合
            Class.forName(PROPERTIES.getProperty("driver"));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(PROPERTIES.getProperty("url"),
            PROPERTIES.getProperty("username"), PROPERTIES.getProperty("password"));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
   

十. ORM

ORM(Object Relational Mapping)。
从数据库查询到的结果集(ResultSet)在进行遍历时,逐行遍历,取出的都是零散的数据。在实际应用开发中,我们需要将零散的数据进行封装整理。
   
10.1 实体类
一行数据中,多个零散的数据进行整理。
通过entity的规则对表中的数据进行对象的封装。
表名=类名;列名=属性名;提供各个属性的get、set方法。
提供无参构造方法、(视情况添加有参构造)。
      
10.1.1 ORM应用
entity实体类
package com.www.test;

public class T_Jobs {
    private String job_id;
    private String job_title;
    private int min_salary;
    private int max_salary;
    @Override
    public String toString() {
        return "T_Jobs{" +
        "job_id='" + job_id + '\'' +
        ", job_title='" + job_title + '\'' +
        ", min_salary=" + min_salary +
        ", max_salary=" + max_salary +
        '}';
    }
    public String getJob_id() {
        return job_id;
    }
    public void setJob_id(String job_id) {
        this.job_id = job_id;
    }
    public String getJob_title() {
        return job_title;
    }
    public void setJob_title(String job_title) {
        this.job_title = job_title;
    }
    public int getMin_salary() {
        return min_salary;
    }
    public void setMin_salary(int min_salary) {
        this.min_salary = min_salary;
    }
    public int getMax_salary() {
        return max_salary;
    }
    public void setMax_salary(int max_salary) {
        this.max_salary = max_salary;
    }
    public T_Jobs() {
    }
    public T_Jobs(String job_id, String job_title, int min_salary, int max_salary) {
        this.job_id = job_id;
        this.job_title = job_title;
        this.min_salary = min_salary;
        this.max_salary = max_salary;
    }
}
   
查询结果封装
package com.www.test;

import java.sql.*;

public class JobsQuery {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        String URL = "jdbc:mysql://localhost:3306/product";
        String user = "root";
        String password = "1234";
        try {
            //1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取数据库连接对象
            connection = DriverManager.getConnection(URL, user, password);
            //3.编写 SQL 语句
            String sql = "select * from t_jobs";
            //4.获取发送 sql 语句对象
            statement = connection.createStatement();
            //5.执行 SQL 语句并接收结果集
            resultSet = statement.executeQuery(sql);
            //5.1使用 while 循环判断下一行是否有数据
            while(resultSet.next()){
                //5.2有数据,依据列名获取数据
                String job_id = resultSet.getString(1);
                String job_title = resultSet.getString(2);
                int min_salary = resultSet.getInt(3);
                int max_salary = resultSet.getInt(4);
                //5.3 创建实体类对象
                T_Jobs t_jobs = new T_Jobs();
                //5.4 每列数据对应属性进行赋值
                t_jobs.setJob_id(job_id);
                t_jobs.setJob_title(job_title);
                t_jobs.setMin_salary(min_salary);
                t_jobs.setMax_salary(max_salary);
                System.out.println(t_jobs);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                //6.释放资源
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
   

十一. 数据访问对象

DAO 实现了业务逻辑与数据库访问相分离。
        对同一张表的所有操作封装在XxxDaoImpl对象中。
        根据增删改查的不同功能实现具体的方法(insert、update、delete、select、 selectAll)。

  
11.1 创建数据库
创建一张表 Person,有以下列:
        id:int,主键,自动增长
        name:varchar(20) 非空
        age:int 非空
        bornDate:Date
        email:字符串
        address:字符串
   
11.2 封装实体类
创建entity实体类 Person,编写属性私有化,构造方法,get/set 方法。
  
11.3 编写 DaoImpl 类
编写 DaoImpl 类,提供增删改查方法,使用 JDBC 开发步骤,完成功能。
package com.person;

import sun.awt.image.DataBufferNative;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* 增、删、改、查单个、查所有
* 只做数据库访问操作!不参与逻辑判断
* 数据库一张表的访问的操作复用!
*/

public class PersonDaoImpl {
    //新增
    public int insert(Person person){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        String sql = "insert into person(name,age,borndate,email,address) values(?,?,?,?,?);";
        try {
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,person.getName());
            preparedStatement.setInt(2,person.getAge());
            preparedStatement.setDate(3,null);
            preparedStatement.setString(4,person.getEmail());
            preparedStatement.setString(5,person.getAddress());
            int result = preparedStatement.executeUpdate();
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }
    //修改
    public int update(Person person){
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        String sql = "update person set
        name=?,age=?,borndate=?,email=?,address=? where id = ?";
        try {
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,person.getName());
            preparedStatement.setInt(2,person.getAge());
            preparedStatement.setDate(3,null);
            preparedStatement.setString(4,person.getEmail());
            preparedStatement.setString(5,person.getAddress());
            preparedStatement.setInt(6,person.getId());
            int result = preparedStatement.executeUpdate();
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }
    //删除
    public int delete(int id){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        String sql = "delete from person where id= ?;";
        connection = DBUtils.getConnection();
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            int result = preparedStatement.executeUpdate();
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }
    //查单个
    public Person select(int id){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "select * from person where id = ?;";
        Person person = null;
        try {
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            resultSet = preparedStatement.executeQuery();
            if(resultSet.next()){
                person = new Person();
                int pid= resultSet.getInt("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                Date bornDate = resultSet.getDate("borndate");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                person.setId(pid);
                person.setName(name);
                person.setAge(age);
                person.setBornDate(bornDate);
                person.setEmail(email);
                person.setAddress(address);
            }
            return person;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.closeAll(connection,preparedStatement,resultSet);
        }
        return null;
    }
    //查所有
    public List<Person> selectAll(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Person person = null;
        List<Person> personList = new ArrayList<>();
        try {
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement("select * from person;");
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){
                int pid= resultSet.getInt("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                Date bornDate = resultSet.getDate("borndate");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                person = new Person(pid,name,age,bornDate,email,address);
                personList.add(person);
            }
            return personList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
  

十二. 三层架构

12.1 什么是三层
 表示层:
命名:XXXView
职责:收集用户的数据和需求、展示数据。
   
业务逻辑层:
命名:XXXServiceImpl
职责:数据加工处理、调用DAO完成业务实现、控制事务。
   
数据访问层:
命名:XXXDaoImpl
职责:向业务层提供数据,将业务层加工后的数据同步到数据库。

   
12.2 三层搭建
utils 存放工具类(DBUtils)
entity 存放实体类(Person)
dao 存放 DAO 接口(PersonDao)
        impl 存放 DAO 接口实现类(PersonDaoImpl)
service 存放 service 接口(PersonService)
        impl 存放 service 接口实现类(PersonServiceImpl)
view 存放程序启动类(main)
程序设计时,考虑易修改、易扩展,为Service层和DAO层设计接口,便于未来更换实现类。
     

十三. 通用工具类

在DAO层中,对数据库表的增、删、改、查操作存在代码冗余,可对其进行抽取封装DaoUtils工具类实现复用。
  
13.1通用DML
/**
* 将所有数据表的操作,抽离成一个公用的方法;
* @Param sql 语句
* @Param sql语句对应的参数
* @return
*/
public static boolean executeDML(String sql,Object... params){
    try {
        //获取连接
        Connection connection = getConnection();
        //获取预处理的对象
        PreparedStatement ps = connection.prepareStatement(sql);
        //设置参数
        if(null != params){
            for(int i = 0 ; i < params.length ; i++){
                //1:给占位符设置参数;2:获取参数
                ps.setObject(i+1,params[i]);
            }
        }
        int i = ps.executeUpdate();
        close(null,ps,connection);
        return i > 0;
    } catch (SQLException sqlException) {
        sqlException.printStackTrace();
    }
    return false;
}
  
13.2 通用DQL
/**
* 通用的查询;需要将我们的数据表信息,封装到List里面进行返回
* @param sql 查询语句
* @param cls 实体类的字节码对象
* @param params 查询语句里面的占位符
* @param <T> 实体类类型泛型
* @return 就是我们查询到的数据集合
*/

public static <T> List<T> executeDQL(String sql, Class<T> cls , Object...params) {
    try {
        Connection connection = getConnection(); //获取连接
        //获取预处理sql
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置参数
        if(null != params){
            for(int i = 0 ; i < params.length ; i++){
                preparedStatement.setObject(i+1,params[i]);
            }
        }
        //执行查询 得到结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //获取元数据(我们的列名)
        ResultSetMetaData metaData = resultSet.getMetaData();
        //列的总数
        int columnCount = metaData.getColumnCount();
        //用来保存我们所有的表数据
        List<T> list = new ArrayList<T>();
        T t;//用来保存我们一条数据
        //遍历结果集
        while(resultSet.next()){ //每一行记录的遍历过程中
            t = cls.newInstance();//根据字节码文件,构建一个实体类的对象
            //获取所有列的数据
            for(int i = 1 ; i <= columnCount ; i++){
                //你的查询语句有时候有别名
                String columnLabel = metaData.getColumnLabel(i);
                //根据列名获取我们的记录
                Object object = resultSet.getObject(columnLabel);
                //需要将拿到的这一列的记录,放到t对象指定的属性里面;
                //需要拿到这个t对象的属性,然后赋值;
                //解决方案2: 如果Object是NULL没有必要设置了
                if(null != object){
                    try {
                        Field field = cls.getDeclaredField(columnLabel);//根据属性的名称通过反射获取他的属性对象
                        field.setAccessible(true);
                        field.set(t,object);
                    } catch (NoSuchFieldException e) {
                        //代表我们当前这个实体类里面,没有这个属性
                    }
                }
            }
            //需要将t对象保存到list
            list.add(t);
        }
        close(resultSet,preparedStatement,connection);
        return list;
    } catch (SQLException sqlException) {
        sqlException.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    }
    return null;
}
   
13.3 Apache的DbUtils
13.3.1 简介
DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用。
        对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。
        对于数据表的DML操作,也变得很简单(只需要写SQL语句)。
  
13.3.2 API
ResultSetHandler接口:转换类型接口
        BeanHandler类:实现类,把一条记录转换成对象
        BeanListHandler类:实现类,把多条记录转换成List集合。
        ScalarHandler类:实现类,适合获取一行一列的数据。
QueryRunner:执行sql语句的类
        增、删、改:update();
        查询:query();
  
13.3.3 使用步骤
导入jar包
        mysql连接驱动jar包
        druid-1.1.5.jar
        database.properties配置文件
        commons-dbutils-1.6.jar
     
13.3.4 代码
package com.project.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* 连接池工具类
*/

public class DBUtils {
    private static DruidDataSource dataSource;
    static {
        Properties properties = new Properties();
        InputStream is = DBUtils.class.getResourceAsStream("/database.properties");
        try {
            properties.load(is);
            dataSource = (DruidDataSource)
            DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 返回一个数据源
    public static DataSource getDataSource(){
        return dataSource;
    }
}
package com.project.dao.impl;

import com.project.dao.UserDao;
import com.project.entity.User;
import com.project.utils.DBUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;

public class UserDaoImpl implements UserDao {
    //1.创建QueryRunner对象,并传递一个数据源对象
    private QueryRunner queryRunner = new QueryRunner(DBUtils.getDataSource());
    @Override
    public int insert(User user) {
        Object[] params={user.getId(),user.getUsername(),user.getPassword(),user.getSex(),user.getEmail(),user.getAddress()};
        try {
            return queryRunner.update("insert into user(id,username,password,sex,email,address) values(?,?,?,?,?,?)",params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public int update(User user) {
        Object[] params={user.getUsername(),user.getPassword(),user.getSex(),user.getEmail(),user.getAdd ress(),user.getId()};
        try {
            return queryRunner.update("update user set
            username=?,password=?,sex=?,email=?,address=? where id = ?",params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public int delete(int id) {
        try {
            return queryRunner.update("delete from user where id = ?",id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public User select(int id) {
        try {
            //把查询到的记录封装成 指定对象
            return queryRunner.query("select * from user where id = ?", new
            BeanHandler<User>(User.class), id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
    * 查询所有
    * @return
    */
    @Override
    public List<User> selectAll() {
        try {
            return queryRunner.query("select * from user;",new
            BeanListHandler<User>(User.class));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  

十四. 连接池

在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。
资源重用。
更快的系统响应速度。
新的资源分配手段。
统一的连接管理,避免数据库连接泄漏。
  
14.1 Druid
14.1.1 步骤
创建 druid.properties 配置文件。
引入druid-xxx.jar 文件。
  
14.1.2 druid.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytest
username=root
password=123456
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
maxWait=5000
    
14.1.3 连接池工具类
public class DbUtils {
    //声明连接池对象
    private static DruidDataSource ds;
    static{
        //实例化配置对象
        Properties properties=new Properties();
        try {
            //加载配置文件内容
            properties.load(DbUtils.class.getResourceAsStream("druid.properties"));
            ds = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获取连接对象
    public static Connection getConnection() {
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //释放资源。。
}
   
14.2 HikariCP
引入HikariCP-xxx.jar 文件。
/*
一、主要配置
1、dataSourceClassName
这是DataSourceJDBC驱动程序提供的类的名称。请注意,如果您正在使用jdbcUrl“旧式”基于DriverManager的JDBC驱动程序配置,则不需要此属性 。 默认值:无
2、jdbcUrl
请注意,如果使用此属性,您仍然可以使用DataSource属性来配置您的驱动程序,实际上建议您使用URL本身中指定的驱动程序参数。 默认值:无
3、username
此属性设置从基础驱动程序获取连接时使用的默认身份验证用户名。
4、password
此属性设置从基础驱动程序获取连接时使用的默认身份验证密码。
*/
public static void main(String[] args) throws SQLException {
    HikariConfig hikariConfig = new HikariConfig();
    //设置url
    hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/mytest?characterEncoding=UTF-8");
    //数据库帐号
    hikariConfig.setUsername("root");
    //数据库密码
    hikariConfig.setPassword("123456");
    HikariDataSource ds = new HikariDataSource(hikariConfig);
}
    

十五 . 批处理

addBatch(); 添加到批处理
executeBatch(); 执行批处理
clearBatch(); 清空批处理
//如果保存1w条记录
String sql = "insert into userinfo(uname,upass) values(?,?)";
Connection connection = DBUtilPool.getConnectionByDruid();
long start = System.currentTimeMillis();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for(int i = 0 ; i < 10000 ; i++){
    preparedStatement.setObject(1,"jack"+i);
    preparedStatement.setObject(2,"aaaa"+i);
    preparedStatement.addBatch(); //将当前的sql预编译好以后,加到批处理; 不会直接执行到数据库里面
    if(i % 500 == 0){
        preparedStatement.executeBatch(); //执行我们批处理
        preparedStatement.clearBatch(); //把上面的执行了,需要清空
    }
}
preparedStatement.executeBatch(); //最后一次进行批处理
long end = System.currentTimeMillis();
System.out.println("");
System.out.println(end-start);
  

十六. 事务

16.1 业务
代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成。(软件所提供的一个功能都叫业务)。
  
16.2 service层

   
16.3 转账案例
BEGIN ;-- 代表我们开启了一个事务
UPDATE user_acount SET umoney = umoney-200 WHERE uname = 'jack';

-- 断网了 断电了
UPDATE user_acount SET umoney = umoney+200 WHERE uname = 'rose';

ROLLBACK -- 回滚事务(代表整个事务执行失败)
COMMIT; -- 提交事务
   
16.4 事务
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
   
16.5 转账事务案例
-- 默认提交事务
begin;
commit; -- 提交事务
rollback; -- 事务回滚

//代码里面默认回滚事务
connection.setAutoCommit(false); //不自动提交事务
connection.commit();//提交事务
connection.rollback();//回滚事务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1323524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL的增删改查(进阶)--上

1. 数据库约束 1.1 约束类型 NOT NULL - 指示某列不能存储 NULL 值。 UNIQUE - 保证某列的每行必须有唯一的值。 DEFAULT - 规定没有给列赋值时的默认值。 PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列&#xff08;或两个列多个列的结合&#xff09;有唯一标识&#xf…

3-10岁孩子数学发展里程碑

文章目录 3岁4岁5岁6-7岁&#xff08;1-2年级&#xff09;8-9岁&#xff08;3-4年级&#xff09;10岁&#xff08;5年级&#xff09; 当然&#xff0c;孩子的数学能力发展会因个体差异而有所不同&#xff0c;但以下是一个大致的指导&#xff0c;用来描述从3岁到10岁孩子在数学上…

HPM6750系列--第十一篇 Uart讲解(轮询模式)

一、目的 在介绍完GPIO的相关内容下一个必须介绍的就是uart了&#xff0c;因为串口一个主要用途就是用于调试信息打印。 HPM6750在uart的配置上也是相当炸裂&#xff0c;有17个串口&#xff1b;结合HPM6750的高主频高内存&#xff0c;完全可以作为一个串口服务器。 ​​​​​​…

Pycharm enable IntelliBot #patched后,工程无法打开

#本地环境# Pycharm&#xff1a;2023.12 Pro 对应robot pkg版本&#xff1a; robotframework 6.1 robotframework-databaselibrary 1.2.4 robotframework-pythonlibcore 4.1.2 robotframework-requests 0.9.4 robotframework-seleniumlibrary 6.1.…

新增工具箱管理功能、重构网站证书管理功能,1Panel开源面板v1.9.0发布

2023年12月18日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.9.0版本。 在这一版本中&#xff0c;1Panel引入了新的工具箱管理功能&#xff0c;包含Swap分区管理、Fail2Ban管理等功能。此外&#xff0c;1Panel针对网站证书管理功能进行了全面重构&…

移动云捐赠三款开源项目,加速新一代基础软件生态繁荣

随着云计算、大数据、人工智能等新领域新信息技术的发展&#xff0c;我国基础软件的自主可控极大程度地影响着产业链上下游的多样性和技术创新的发展空间。移动云作为中国移动涉云业务的主入口&#xff0c;一直坚持共享开源价值&#xff0c;积极推动中国开源软件生态的繁荣发展…

UE5 水材质注意要点

1、两个法线反向交替流动&#xff0c;可以去观感假的现象 2、水面延边的透明度低 3、增加水面延边的浪花 4、增加折射 折射要整体质量至少在High才有效果 改为半透明材质没有法线信息&#xff1f; 5、处理反射效果 勾选为true 找到这个放在水域 勾为false&#xff0c;即可有非…

基于ssm品牌手机销售信息系统论文

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于品牌手机销售信息系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了品牌手机销售信息系统&#xff0c;它彻底…

05_Web框架之Django二

Web框架之Django二 学习目标和内容 1、能够使用类视图的写法 2、能够使用模板语言的相关语法 3、能够理解过滤器的作用 4、能够理解并使用模板继承 一、类视图 1、类视图介绍 视图是一个可调用的对象&#xff0c;它接收一个请求然后返回一个响应&#xff0c;这个可调用对象可…

phpmyadmin4.8.1远程文件包含漏洞 [GWCTF 2019]我有一个数据库1

打开题目 我们用dirsearch扫描一下后台看看 扫描结果如下 我们访问一下robots.txt看看&#xff0c;提示有phpinfo.php 那我们访问一下phpinfo.php 发现没有任何信息后我们转去看看phpmyadmin看看 成功访问到页面 在这里我们看到phpmyadmin的版本号是4.8.1 我们百度搜索一下看…

Java版企业电子招投标系统源代码,支持二次开发,采用Spring cloud微服务架构

招投标管理系统是一个集门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理于一体的综合性应用平台。它适用于招标代理、政府采购、企业采购和工程交易等业务的企业&#xff0c;旨在提高项目管理的效率和质量。该系…

linux搭建gitlab

gitlab的介绍 区别于github&#xff0c;github是面向互联网基于git实现的代码托管平台&#xff0c;gitlab是基于Ruby语言实现的git管理平台软件&#xff0c;一般用于公司内部代码仓库。 gitlab组成 Nginx 静态Web服务器Gitlab-workhorse 轻量级的反向代理服务器Gitlab-shell 用…

spring MVC概述和土门案例(无配置文件开发)

SpringMVC 1&#xff0c;SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤9:浏览器…

Android 大版本升级变更截图方法总结

Android 大版本升级变更截图方法总结 一、Android R (11) 平台二、Android S (12) 平台三、Android U (14) 平台 Android 原生的截屏功能是集成在 SystemUI 中&#xff0c;因此我们普通应用想要获取截图方法&#xff0c;就需要研读下 SystemUI 截屏部分的功能实现。 一、Androi…

RocketMQ系统性学习-SpringCloud Alibaba集成RocketMQ以及消费收发实战

文章目录 Spring Cloud Alibaba 集成 RocketMQ 最佳实践集成依赖DashBoard消息收发实战 Spring Cloud Alibaba 集成 RocketMQ 最佳实践 SpringBoot 相对于 SSM 来说已经很大程度上简化了开发&#xff0c;但是使用 SpringBoot 集成一些第三方的框架&#xff0c;还是需要花费一些…

Nginx快速入门:安装目录结构详解及核心配置解读(二)

0. 引言 上节我们讲解了nginx的应用场景和安装&#xff0c;本节继续针对nginx的各个目录文件进行讲解&#xff0c;让大家更加深入的认识nginx。并通过一个实操案例&#xff0c;带大家来实际认知nginx的核心配置 1. nginx安装目录结构 首先nginx的默认安装目录为&#xff1a;…

【一】FPGA实现SPI协议之SPI协议介绍

【一】FPGA实现SPI协议之SPI协议介绍 一、spi协议解析 spi协议有4根线&#xff0c;主机输出从机输入MOSI、主机输入从机输出MISO、时钟信号SCLK、片选信号SS\CS 。 一般用于主机和从机之间通信。由主机发起读请求和写请求&#xff0c;主机的权限是主动的&#xff0c;从机是被…

web打印技术方案

在B/S应用系统开发中常常遇到表单打印需求&#xff0c;尤其是OA、ERP类的企业运营管理系统&#xff0c;打印的需求很常见&#xff0c;但WEB应用的打印一直以来是一个难题&#xff0c;特别是在应用中完成标签打印&#xff08;如包裹面单、货运标签等&#xff09;、票据打印&…

AI降重工具

WEB版 体验一下 from docx import Document import requestsdef call_api_and_get_content(content, prompt):api_url "http://XXXXXXXX/api?content" content promptresponse requests.get(api_url)if response.status_code 200:api_result response.text.re…

搭建知识付费平台?明理信息科技为你提供全程解决方案

明理信息科技saas知识付费平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和维护…