JAVA 连接 MySql

// 文件路径 D:\ApacheServer\web_java\HelloWorld\src\com\test\TestMysql.java
package com.test;

import java.sql.Connection;
//驱动管理器,获取链接
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.CallableStatement;


public class TestMysql {

    public void testfun() {
        
        // 需要下载 MySQL 驱动 jar 包,下载地址 https://mvnrepository.com/artifact/mysql/mysql-connector-java,这里用到的是 mysql-connector-java-8.0.17.jar。
        //下载的 jar 包 引入项目中有两种方法
        //1、放到 Tomcat 安装目录下的 lib 文件夹内,这里路径是 D:\ApacheServer\apache-tomcat\lib\mysql-connector-java-8.0.17.jar
        //2、设置为java库,将jar放到 D:\ApacheServer\web_java\HelloWorld\WebContent\WEB-INF\lib 中,在eclipase左侧目录中(WEB-INF\lib)选中该jar包右键 Build Path -> Add to Build Path(IDEA编辑器为选中jar包后右键->Add as Library)
        // 连接 MySQL 需要 MySQL 的时区和 java 一致(MySQL 默认 UTC 时区),这里本地是北京时区。修改  MySQL 配置文件 my.ini 在 [mysqld] 项下添加一行 default-time-zone = '+8:00' 重启 MySQL 即可。如果不能修改MySQL配置文件,则将如下 jdbc:mysql://localhost:3306/testdb 改为 jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC 亦可
        try{
            // 注册 JDBC 驱动器(通过反射Class.forName将Driver加入到jvm中)
            // 如果下载的 MySQL jar 包是 5 系列版本,则需要用 com.mysql.jdbc.Driver 注册驱动,而且必须写。com.mysql.jdbc.Driver为mysql驱动jar包中驱动类Driver的路径
            //Class.forName("com.mysql.jdbc.Driver");
            // MySQL jar包 6 以上版本用 com.mysql.cj.jdbc.Driver 注册,并且6以上版本可以不写Class.forName,这里没有写,已注释掉。com.mysql.cj.jdbc.Driver为mysql驱动jar包里驱动类Driver的路径
            //Class.forName("com.mysql.cj.jdbc.Driver");
            // 打开一个连接
            Connection conn = null;
            // localhost 为数据库连接地址,3306 端口号,testDB 为数据库名称。也可在后面加一些参数如 "jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8",这里参数表示如果数据库是utf8编码则允许java将中文存到数据库中
            //也可将数据库用户名密码也作为参数如 "jdbc:mysql://localhost:3306/testdb?user=root&passwprd=123456&characterEncoding=utf8",则此时给 DriverManager.getConnection(db_host); 传一个参数即可
            String db_host  = "jdbc:mysql://localhost:3306/testdb";
            // 用户名
            String user     = "root";
            // 密码
            String password = "123456";
            conn = DriverManager.getConnection(db_host,user,password);
            
            //当开启事务即关闭自动提交(每执行一句提交一次)
            conn.setAutoCommit(false);
            
            // ==================================================== Statement 类处理
            // Statement 对象 SQL指令的'加载器',执行查询 SQL 语句
            Statement statement = conn.createStatement();
            String sql_sel      = "SELECT id, name, age, book_price FROM test_table";
            //statement对象执行 select 语句用 executeQuery 方法,该方法返回ResultSet对象,并且其内有一个指针(默认指向结果集表头而非第一行数据)
            ResultSet result    = statement.executeQuery(sql_sel);
            
            //遍历结果集
            int i = 1;
            //如果结果集有下一行,则指针下移一位成功,并返回true
            while(result.next()){
                //获取对应字段值
                int id            = result.getInt("id");
                String name       = result.getString("name");
                int age           = result.getInt("age");
                //也可根据查询字段的序号获取字段值,当不知道字段名时可用此方法,第一个字段对应 1
                //int age           = result.getInt(3);
                double book_price = result.getDouble("book_price");
                System.out.println("第 " + i + "行 id : " + id + " name : " + name + " age : " + age + " book_price : " + book_price);
                i++;
            }
            
            //执行 insert、update、delete语句用 executeUpdate 方法,该方法返回int对象值为insert、update、delete操作影响的行数 0 可视为操作失败
            String sql_ins      = "INSERT INTO `test_table`(id, name, age, book_price) VALUES(1, 'testname', 30, 1.35)";
            int result_rows     = statement.executeUpdate(sql_ins);
            System.out.println("添加行数 " + result_rows);
            
            
            // ==================================================== PreparedStatement 类处理 SQL指令的'预编译加载器'
            // PreparedStatement 执行插入语句效果更好,原因:1可以写动态参数化的查询,2PreparedStatement比 Statement 更快,3PreparedStatement可以防止SQL注入式攻击
            // preparedStatement对象的 executeUpdate() 方法可执行 insert,update,delete 语句以及 SQL DDL(如建表,改表,删除表等), executeQuery() 方法执行select语句,execute()执行所有语句,效率也最慢
            
            //CallableStatement继承PreparedStatement,PreparedStatement 继承 Statement。CallableStatement比PreparedStatement多个能调用存储过程功能
            //CallableStatement callableStatement = conn.prepareCall(sql_sel);
            
            // ============================ executeUpdate 方法
            //编写预处理 SQL 语句
            String sql_ins= "INSERT INTO `test_table`(id, name, age, book_price) VALUES(?, ?, ?, ?)";
            PreparedStatement preparedStatement = conn.prepareStatement(sql_ins);
            preparedStatement.setInt(1, 3); //插入表数据第 1 个参数 id 的值为 3
            preparedStatement.setString(2, "testName"); //第 2 个参数名称 为testName
            preparedStatement.setInt(3, 40); //第 3 个参数年龄
            preparedStatement.setDouble(4, 32.55); //第 4 个参数书价格
            // 返回值是一个整数,指示受影响的行数(即更新计数)建表,删表等不操作行的语句总返回 0。
            int updateCount = preparedStatement.executeUpdate();
            System.out.println("插入结果 " + updateCount);
            // ============================ executeQuery 方法
            // 执行 select 语句
            preparedStatement = conn.prepareStatement(sql_sel);
            // 获取查询结果,result 遍历查询结果与之前 Statement 类方式一致
            result = preparedStatement.executeQuery();
            // ============================ execute 方法
            preparedStatement = conn.prepareStatement(sql_sel);
            // execute 可用于执行任何SQL语,返回一个 boolean 值,如果执行后第一个结果(有可能返回的是多个结果集合)是 ResultSet(即查询语句结果),则返回 true,否则返回 false。
            boolean isResult = preparedStatement.execute();
            // 如果 execute() 执行的 sql 语句能返回多个结果集合时,PreparedStatement 对象获取下个 getResultSet() 或者 getUpdateCount() 前要先执行 getMoreResults() 使指针下移,然后再执行 getResultSet() 或 getUpdateCount() 获取当前指针指向结果
            //preparedStatement.getMoreResults(); // 多个结果集时,获取下一个结果时才执行,如在 while 循环语句里用,获取第一个结果时不需要执行此语句
            if(isResult) {
                // 如果结果集当前指针指向的返回结果是个 select 查询结果,用 getResultSet 获取,如果执行的是更新语句,则返回的是更新计数,这时就要用 getUpdateCount来获取
                result = preparedStatement.getResultSet();
                // ...
            }else {
                //当某个过程返回两个更新计数,则首先调用方法getUpdateCount()
                updateCount = preparedStatement.getUpdateCount();
                System.out.println("插入结果 " + updateCount);
            }
            
            
            //提交事务
            conn.commit();
            
            //事务回滚
            //conn.rollback();
            
            // 完成后关闭
            if(preparedStatement != null && !preparedStatement.isClosed()){
                preparedStatement.close();
            }
            if(result != null && !result.isClosed()){
                result.close();
            }
            if(statement != null && !statement.isClosed()){
                statement.close();
            }
            if(conn != null && !conn.isClosed()){
                conn.close();
            }
        }catch(SQLException sqlException) {
            // 处理 JDBC 错误
            sqlException.printStackTrace();
        }catch(Exception exception) {
            // 处理 Class.forName 错误
            exception.printStackTrace();
        }
    }
}

 

posted @ 2019-09-08 15:44  风吹屁股凉冰冰  阅读(213)  评论(0编辑  收藏  举报