新年迈出Java后台服务器与数据库交互第一步&2022最新通用Java8&jdbc8连接mysql8数据库进行增删改查等基本操作详解(IDEA),jar包导入,图片等文件流,批量操作

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: 新年迈出Java后台服务器与数据库交互第一步&2022最新通用Java8&jdbc8连接mysql8数据库进行增删改查等基本操作详解(IDEA),jar包导入,图片等文件流,批量操作

文章目录


一、JDBC下载与导入

二、获取连接

三、PreparedStatement类操作数据库

四、操作BLOB类型字段(图片视频等)

五、Batch批量插入


一、JDBC下载与导入


1、jar包下载


👇👇👇划至文末有mysql-connector-java-8.0.27.jar的阿里云盘链接🔗,已经只留下有用的jar包文件了,下载即可用。


2、导入(IDEA)


①在工程下新建一个文件夹(可以命名为libs)


123ec416035241f885d6514b619b2d0d.png


②将下载的jar包复制粘贴到该文件夹里面,然后右键该文件夹选择"Add as Library"


46c27b5bb8194b8aaf4d3f21076b72a2.png


二、获取连接


1、创建配置文件jdbc.properties


配置信息如下:


user=用户(root)
password=数据库密码
url=jdbc:mysql://localhost:3306/test?useUnicode=true&character=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
driverClass=com.mysql.cj.jdbc.Driver



说明:


 
         


使用配置文件的好处:实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码;如果修改了配置信息,省去重新编译的过程。


2、使用DriverManager获取连接


import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
 /**
 * @Author: Yeman
 * @Date: 2022-01-11-21:51
 * @Description:
 */
public class jdbcLinked {
    public static void main(String[] args) throws Exception {
        //1、加载配置文件
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        //2、读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //3、加载驱动
        Class.forName(driverClass);
        //4、获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        System.out.println(conn);
    }
}


三、PreparedStatement类操作数据库


1、PreparedStatement介绍


①通过调用获取连接时生成的 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象。


②PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句。


③PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用PreparedStatement 对象的 setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。


2、PreparedStatement vs Statement


①PreparedStatement 可以防止 SQL 注入问题,且提高代码的可读性和可维护性。


②PreparedStatement 能最大可能提高性能:

DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义,事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。(语法检查,语义检查,翻译成二进制命令,缓存)


③PreparedStatement 便于操作BLOB类型字段(图片视频等文件数据)。


④PreparedStatement 更适于批量操作。


3、Java与SQL对应数据类型转换表


042a7a120ef34f759cd9d90b7e33d4ce.png


4、使用PreparedStatement实现通用增、删、改操作


这里所说的通用是针对于同一数据库下的不同表或同一张表的不同DML。


①工具类(包括获取连接,通用增删改,关闭连接)


package utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
 * @Author: Yeman
 * @Date: 2022-01-12-14:34
 * @Description:操作数据库的工具类
 */
public class jdbcUtils {
    /**
     * @Description 获取数据库连接
     * @Param []
     * @return java.sql.Connection
     **/
    public static Connection getSqlConnection() throws Exception{
        //1、加载配置文件
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        //2、读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //3、加载驱动
        Class.forName(driverClass);
        //4、获取连接
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }
    /**
     * @Description 关闭连接和Statement资源
     * @Param [conn, ps]
     * @return void
     **/
    public static void closeResource(Connection conn, Statement ps){
        try {
            if (ps != null) ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
  //重载
    public static void closeResource(Connection conn, Statement ps, ResultSet res){
        try {
            if (ps != null) ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (res != null) res.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /**
     * @Description 通用增删改操作
     * @Param [sql, args]
     * @return void
     **/
    public static int updateDate(String sql, Object... args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //获取数据库连接
            conn = getSqlConnection();
            //预编译sql语句,获取PreparedStatement实例
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            //执行操作
            return ps.executeUpdate(); //返回操作的字段数,没有则为0
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            closeResource(conn, ps);
        }
        return 0;
    }
}


②测试类


package jdbc;
import utils.jdbcUtils;
/**
 * @Author: Yeman
 * @Date: 2022-01-12-20:51
 * @Description:
 */
public class comUpdate {
    public static void main(String[] args) {
        String sql = "update `order` set order_name = ? where order_id < ?";
        int bb = jdbcUtils.updateDate(sql, "BB", 4);
        System.out.println(bb);
    }
}


5、使用PreparedStatement实现通用查询操作


这里所说的通用是针对同一数据库下的不同表或者同一张表的不同查询字段数。而要实现不同表的通用,则首先需要创建相应的不同Java类,即依据ORM思想。


/*
 * ORM编程思想(object relational mapping)
 * 一个数据表对应一个Java类
 * 表中的一条记录对应Java类的一个对象,一个字段对应Java类的一个属性
 */


例如,我这里的数据库中有一张customers表,因此我需要创建一个customers类。


package javabean;
import java.sql.Date;
/**
 * @Author: Yeman
 * @Date: 2022-01-12-21:08
 * @Description: customers表对应的Java类
 */
public class Customers {
    private int id;
    private String name;
    private String email;
    private Date birth;
    public Customers() {
    }
    public Customers(int id, String name, String email, Date birth) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.birth = birth;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public String getEmail() {
        return email;
    }
    public Date getBirth() {
        return birth;
    }
    @Override
    public String toString() {
        return "Customers{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birth=" + birth +
                '}';
    }
}


①工具类(连接与关闭),即调用上面的Utils


②通用查询类


import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author: Yeman
 * @Date: 2022-01-13-20:45
 * @Description:
 */
public class Query {
    public static <T> List<T> Query(Class<T> clazz, String sql, Object... args) {
        ArrayList<T> ts = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet res = null;
        try {
            //获取连接
            conn = jdbcUtils.getSqlConnection();
            //预编译sql语句,获取PreparedStatement实例
            ps = conn.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            //获取结果集
            res = ps.executeQuery();
            //获取结果集元数据
            ResultSetMetaData metaData = res.getMetaData();
            //获取列数
            int columnCount = metaData.getColumnCount();
            //处理结果集数据
            while (res.next()){
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    Object value = res.getObject(i + 1); //获取列值
                    String columnLabel = metaData.getColumnLabel(i + 1); //获取列的别名
                    //通过反射实现
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,value);
                }
                ts.add(t);
            }
            return ts;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            jdbcUtils.closeResource(conn,ps,res);
        }
        return null;
    }
}


四、操作BLOB类型字段(图片视频等)


1、MySQL BLOB类型


MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。


MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)


424d56e28585411f8717ebb35b60a157.png


实际使用中根据需要存入的数据大小定义不同的BLOB类型。但需要注意的是,如果存储的文件过大,数据库的性能会下降。


如果在指定了相关的Blob类型以后,还报错:xxx too large,那么需要在mysql的安装目录下,打开my.ini文件最后加上 max_allowed_packet=16M 。修改my.ini文件之后,需要重新启动mysql服务才能生效。(找不到my.ini文件或者无法修改可以留言或者私信)


2、向数据表中增(改)大数据类型


package jdbc;
import utils.jdbcUtils;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
 * @Author: Yeman
 * @Date: 2022-01-13-22:13
 * @Description:
 */
public class Blob01 {
    public static void main(String[] args) throws Exception {
        //获取连接
        Connection conn = jdbcUtils.getSqlConnection();
        //预编译sql语句,获取PreparedStatement实例
        String sql = "insert into customers(name,email,birth,photo) values(?,?,?,?)";
        PreparedStatement ps = conn.prepareStatement(sql);
        //填充占位符
        ps.setObject(1,"叶绿体");
        ps.setObject(2,"yelvti@163.com");
        ps.setObject(3,"2000-01-01");
            //即以流的形式读取图片文件后再添加到数据库中(增和改类似)
        FileInputStream photo = new FileInputStream(new File("a.jpg"));
        ps.setObject(4,photo);
        //执行
        ps.execute();
        //关闭连接
        jdbcUtils.closeResource(conn,ps);
    }
}


3、从数据库表中读取大数据类型


package jdbc;
import javabean.Customers;
import utils.jdbcUtils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
/**
 * @Author: Yeman
 * @Date: 2022-01-13-22:34
 * @Description:这里以customer表为例,该表中有一photo图片类型数据
 */
public class Blob02 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet res = null;
        InputStream is = null;
        FileOutputStream os = null;
        try {
            conn = jdbcUtils.getSqlConnection();
            String sql = "select id,name,email,birth,photo from customers where id = ?";
            ps = conn.prepareStatement(sql);
            ps.setObject(1,16);
            res = ps.executeQuery();
            while (res.next()){
                int id = res.getInt("id");
                String name = res.getString("name");
                String email = res.getString("email");
                Date birth = res.getDate("birth");
                Customers customers = new Customers(id, name, email, birth);
                System.out.println(customers);
                //以二进制流的形式读取下来写到本地
                Blob photo = res.getBlob("photo");
                is = photo.getBinaryStream();
                os = new FileOutputStream("zhuyin.jpg");
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1){
                    os.write(buffer,0,len);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            jdbcUtils.closeResource(conn,ps,res);
        }
    }
}


五、Batch批量插入


1、批量执行SQL语句


当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常比单独提交处理具有更高的效率。


JDBC 的批量处理语句包括下面三个方法:

①addBatch(String):添加需要批量处理的SQL语句或参数;

②executeBatch():执行批量处理语句;

③clearBatch():清空缓存的数据。


2、高效的批量插入


mysql服务器默认是关闭批量处理的,我们需要通过一个参数,让mysql开启批处理的支持。即将 ?rewriteBatchedStatements=true 补充在配置文件jdbc.properties的 url 的参数位置。


举例:向数据表goods中插入20000条数据


package jdbc;
import utils.jdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
 * @Author: Yeman
 * @Date: 2022-01-14-12:09
 * @Description: 批量操作
 */
public class goods {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            long begin = System.currentTimeMillis();
            //获取连接
            conn = jdbcUtils.getSqlConnection();
            //设置为不可自动提交
            conn.setAutoCommit(false);
            //预编译sql语句,获取PreparedStatement实例
            String sql = "insert into goods(name) value(?)";
            ps = conn.prepareStatement(sql);
            //填充占位符,使用Batch积攒要执行的sql
            for (int i = 1; i <= 1000000; i++) {
                ps.setString(1, "name" + i);
                //攒sql
                ps.addBatch();
                //执行(这里设置为每5000条执行一次)
                if (i % 5000 == 0){
                    ps.executeBatch();
                    //清空
                    ps.clearBatch();
                }
            }
            //使其提交
            conn.commit();
            long end = System.currentTimeMillis();
            System.out.println("花费的时间为:" + (end - begin));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭连接
            jdbcUtils.closeResource(conn,ps);
        }
    }
}


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
10月前
|
存储 Oracle 关系型数据库
服务器数据恢复—光纤存储上oracle数据库数据恢复案例
一台光纤服务器存储上有16块FC硬盘,上层部署了Oracle数据库。服务器存储前面板2个硬盘指示灯显示异常,存储映射到linux操作系统上的卷挂载不上,业务中断。 通过storage manager查看存储状态,发现逻辑卷状态失败。再查看物理磁盘状态,发现其中一块盘报告“警告”,硬盘指示灯显示异常的2块盘报告“失败”。 将当前存储的完整日志状态备份下来,解析备份出来的存储日志并获得了关于逻辑卷结构的部分信息。
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
NoSQL Java API
在Java环境下如何进行Redis数据库的操作
总的来说,使用Jedis在Java环境下进行Redis数据库的操作,是一种简单而高效的方法。只需要几行代码,就可以实现复杂的数据操作。同时,Jedis的API设计得非常直观,即使是初学者,也可以快速上手。
466 94
|
10月前
|
Oracle 关系型数据库 数据库
数据库数据恢复—服务器异常断电导致Oracle数据库报错的数据恢复案例
Oracle数据库故障: 某公司一台服务器上部署Oracle数据库。服务器意外断电导致数据库报错,报错内容为“system01.dbf需要更多的恢复来保持一致性”。该Oracle数据库没有备份,仅有一些断断续续的归档日志。 Oracle数据库恢复流程: 1、检测数据库故障情况; 2、尝试挂起并修复数据库; 3、解析数据库文件; 4、导出并验证恢复的数据库文件。
|
前端开发 JavaScript Java
Java中将图片转换为base64格式的技巧
这样,你就可以在Java中将图片转换为Base64格式了。这个方法的实现非常简单,只需要使用Java的内置库,无需任何额外的库。希望这个方法对你有所帮助。
830 22
|
Java 关系型数据库 MySQL
Java汽车租赁系统源码(含数据库脚本)
Java汽车租赁系统源码(含数据库脚本)
569 4
|
SQL Java 关系型数据库
如何通过idea连接mysql实现简单的CRUD
如何通过idea连接mysql实现简单的CRUDhttp://www.bieryun.com/3458.html 大三考研狗,本来不想写博客了,有点浪费时间。后来想一想,就利用零碎时间时间来写。 许多萌新,也许刚接触idea,觉得哇,好强大,的确如此。
2178 0
|
Java 应用服务中间件 Maven
在IntelliJ IDEA中如何配置使用Maven以创建Tomcat环境
所以,别担心这些工具看起来有些吓人,实际上这些都是为了帮助你更好的完成工作的工具,就像超市里的各种烹饪工具一样,尽管它们看起来可能很复杂,但只要你学会用,它们会为你烹饪出一道道美妙的食物。这就是学习新技能的乐趣,让我们一起享受这个过程,攀登知识的高峰!
784 27
|
Java 应用服务中间件 Apache
在IntelliJ IDEA中使用Maven配置Tomcat环境
此配置方法具有较高的实用性,简单易懂。遵循以上步骤,您将能顺利在IntelliJ IDEA中使用Maven配置Tomcat环境,从而进行Web项目的开发和调试。
1608 18
|
IDE 程序员 开发工具
只用正版!教你5个方法,白嫖JetBrains家族的所有产品,包含:IntelliJ IDEA、PyCharm、WebStorm、CLion、Rider
程序员晚枫分享了5种官方认证的免费使用JetBrains家族产品的方法,包括内容创作者计划、开源项目支持、教育许可证、用户组支持和开发者认可计划。这些方法帮助个人开发者与小型团队合法获取强大开发工具,如IntelliJ IDEA、PyCharm等,降低开发成本,提升效率。同时提醒大家遵守使用规范,尊重知识产权。
2603 13