• JDBC编程


    SQL语句主要分为五种:

    1. 查询语句:主要由select关键字完成,查询语句是SQL语句中最复杂、功能最丰富的语句;

    2. DML(Data Manipulation Language,数据操作语言):包含insert、update、delete

    3. DDL(Data Definition Language, 数据定义语言):包含create、 alter、drop、truncate

    4. DCL(Data Control Language,数据控制语言):包含grant 、revoke

    5. 事务控制语句: commit、rollback、savepoint

    JDBC编程步骤:

    1. 加载数据库驱动。通过Class类的forName()静态方法来加载驱动

    Class.forName(driverClass)

    2. 通过DriverManager获取数据库连接Connection对象。

    DriverManager.getConnection(String url,String user,String pass)

    3. 通过Connection对象创建Statement对象。创建Statement有三种方法。

    • createStatement(): 创建基本的Statement对象
    • prepareStatement(String sql): 根据传入的SQL语句创建预编译的Statement对象
    • prepareCall(String sql): 根据传入的SQL语句创建CallableStatement对象。

    4. 使用Statement执行SQL语句。

    execute(): 可以执行任何SQL语句,但比较麻烦,在不清SQL语句类型时,只能使用这个方法。

    executeUpdate():主要用于执行DML和DDL语句。执行DML语句返回受SQL语句影响的行数,执行DDL语句返回0。

    executeQuery():只能执行查询语句,执行后返回代表查询结果的ResultSet对象。

    5. 操作结果集。有两类方法来操作结果集:

    • next()、 previous()、 first()、 last()、 beforeFirst()、 afterLast()、 absolute()
    • getXxx()方法获取记录指针指向行、特定列的值。

    6. 回收数据库资源,包括ResultSet、Statement和Connection等资源。

    例子:

    import java.sql.*;
    
    public class ConnMySql
    {
        public static void main(String[] args) throws Exception
        {
            // 1.加载驱动,使用反射的知识,现在记住这么写。
            Class.forName("com.mysql.jdbc.Driver");
            try(
                // 2.使用DriverManager获取数据库连接,
                // 其中返回的Connection就代表了Java程序和数据库的连接
                // 不同数据库的URL写法需要查驱动文档知道,用户名、密码由DBA分配
                Connection conn = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1:3306/select_test"
                    , "root" , "32147");
                // 3.使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement();
                // 4.执行SQL语句
                /*
                Statement有三种执行sql语句的方法:
                1 execute 可执行任何SQL语句。- 返回一个boolean值,
                  如果执行后第一个结果是ResultSet,则返回true,否则返回false
                2 executeQuery 执行Select语句 - 返回查询到的结果集
                3 executeUpdate 用于执行DML语句。- 返回一个整数,
                  代表被SQL语句影响的记录条数
                */
                ResultSet rs = stmt.executeQuery("select s.* , teacher_name"
                    + " from student_table s , teacher_table t"
                    + " where t.teacher_id = s.java_teacher"))//在try语句中,执行完后会自动关闭。
            {
                // ResultSet有系列的getXxx(列索引 | 列名),用于获取记录指针
                // 指向行、特定列的值,不断地使用next()将记录指针下移一行,
                // 如果移动之后记录指针依然指向有效行,则next()方法返回true。
                while(rs.next())
                {
                    System.out.println(rs.getInt(1) + "	"
                        + rs.getString(2) + "	"
                        + rs.getString(3) + "	"
                        + rs.getString(4));
                }
            }
        }
    }
    View Code

     执行DDL语句的例子:

    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class ExecuteDDL
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)
            throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void createTable(String sql)throws Exception //注意这个返回值类型
        {
            // 加载驱动
            Class.forName(driver);
            try(
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url , user , pass);
            // 使用Connection来创建一个Statment对象
            Statement stmt = conn.createStatement())
            {
                // 执行DDL,创建数据表
                stmt.executeUpdate(sql);
            }
        }
        public static void main(String[] args) throws Exception
        {
            ExecuteDDL ed = new ExecuteDDL();
            ed.initParam("mysql.ini");
            ed.createTable("create table jdbc_test "
                + "( jdbc_id int auto_increment primary key, "
                + "jdbc_name varchar(255), "
                + "jdbc_desc text);");
            System.out.println("-----建表成功-----");
        }
    }
    View Code

    执行DML语句的例子 :

    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class ExecuteDML
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile)
            throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public int insertData(String sql)throws Exception//注意这里的返回值类型
        {
            // 加载驱动
            Class.forName(driver);
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass);
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement())
            {
                // 执行DML,返回受影响的记录条数
                return stmt.executeUpdate(sql);
            }
        }
        public static void main(String[] args)throws Exception
        {
            ExecuteDML ed = new ExecuteDML();
            ed.initParam("mysql.ini");
            int result = ed.insertData("insert into jdbc_test(jdbc_name,jdbc_desc)"
                + "select s.student_name , t.teacher_name "
                + "from student_table s , teacher_table t "
                + "where s.java_teacher = t.teacher_id;");
            System.out.println("--系统中共有" + result + "条记录受影响--");
        }
    }
    View Code

     当不清楚SQL语句类型时的例子:

    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class ExecuteSQL
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void executeSql(String sql)throws Exception
        {
            // 加载驱动
            Class.forName(driver);
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass);
                // 使用Connection来创建一个Statement对象
                Statement stmt = conn.createStatement())
            {
                // 执行SQL,返回boolean值表示是否包含ResultSet
                boolean hasResultSet = stmt.execute(sql);
                // 如果执行后有ResultSet结果集
                if (hasResultSet)
                {
                    try(
                        // 获取结果集
                        ResultSet rs = stmt.getResultSet())
                    {
                        // ResultSetMetaData是用于分析结果集的元数据接口
                        ResultSetMetaData rsmd = rs.getMetaData();
                        int columnCount = rsmd.getColumnCount();
                        // 迭代输出ResultSet对象
                        while (rs.next())
                        {
                            // 依次输出每列的值
                            for (int i = 0 ; i < columnCount ; i++ )
                            {
                                System.out.print(rs.getString(i + 1) + "	");
                            }
                            System.out.print("
    ");
                        }
                    }
                }
                else
                {
                    System.out.println("该SQL语句影响的记录有"
                        + stmt.getUpdateCount() + "条");
                }
            }
        }
        public static void main(String[] args) throws Exception
        {
            ExecuteSQL es = new ExecuteSQL();
            es.initParam("mysql.ini");
            System.out.println("------执行删除表的DDL语句-----");
            es.executeSql("drop table if exists my_test");
            System.out.println("------执行建表的DDL语句-----");
            es.executeSql("create table my_test"
                + "(test_id int auto_increment primary key, "
                + "test_name varchar(255))");
            System.out.println("------执行插入数据的DML语句-----");
            es.executeSql("insert into my_test(test_name) "
                + "select student_name from student_table");
            System.out.println("------执行查询数据的查询语句-----");
            es.executeSql("select * from my_test");
        }
    }
    View Code

    使用PreparedStatement执行SQL语句的例子(使用这种方法,可以防止SQL注入,比如在登录框中输入‘or true or’)

    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class PreparedStatementTest
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
            // 加载驱动
            Class.forName(driver);
        }
        public void insertUseStatement()throws Exception
        {
            long start = System.currentTimeMillis();
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass);
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement())
            {
                // 需要使用100条SQL语句来插入100条记录
                for (int i = 0; i < 100 ; i++ )
                {
                    stmt.executeUpdate("insert into student_table values("
                        + " null ,'姓名" + i + "' , 1)");
                }
                System.out.println("使用Statement费时:"
                    + (System.currentTimeMillis() - start));
            }
        }
        public void insertUsePrepare()throws Exception
        {
            long start = System.currentTimeMillis();
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass);
                // 使用Connection来创建一个PreparedStatement对象
                PreparedStatement pstmt = conn.prepareStatement(
                    "insert into student_table values(null,?,1)"))
    
            {
                // 100次为PreparedStatement的参数设值,就可以插入100条记录
                for (int i = 0; i < 100 ; i++ )
                {
                    pstmt.setString(1 , "姓名" + i);
                    pstmt.executeUpdate();
                }
                System.out.println("使用PreparedStatement费时:"
                    + (System.currentTimeMillis() - start));
            }
        }
        public static void main(String[] args) throws Exception
        {
            PreparedStatementTest pt = new PreparedStatementTest();
            pt.initParam("mysql.ini");
            pt.insertUseStatement();
            pt.insertUsePrepare();
        }
    }
    View Code

    使用CallableStatement调用存储过程的例子

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class CallableStatementTest
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void callProcedure()throws Exception
        {
            // 加载驱动
            Class.forName(driver);
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass);
                // 使用Connection来创建一个CallableStatment对象
                CallableStatement cstmt = conn.prepareCall(
                    "{call add_pro(?,?,?)}"))
            {
                cstmt.setInt(1, 4);
                cstmt.setInt(2, 5);
                // 注册CallableStatement的第三个参数是int类型
                cstmt.registerOutParameter(3, Types.INTEGER);
                // 执行存储过程
                cstmt.execute();
                // 获取,并输出存储过程传出参数的值。
                System.out.println("执行结果是: " + cstmt.getInt(3));
            }
        }
        public static void main(String[] args) throws Exception
        {
            CallableStatementTest ct = new CallableStatementTest();
            ct.initParam("mysql.ini");
            ct.callProcedure();
        }
    }
    View Code

    管理结果集:


    可滚动、可更新的结果集

    需要在创建Statement或者PrepareStatement时传入额外的参数,如下面例子:

    import java.util.*;
    import java.io.*;
    import java.sql.*;
    
    public class ResultSetTest
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void query(String sql)throws Exception
        {
            // 加载驱动
            Class.forName(driver);
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url , user , pass);
                // 使用Connection来创建一个PreparedStatement对象
                // 传入控制结果集可滚动,可更新的参数。
                PreparedStatement pstmt = conn.prepareStatement(sql
                    , ResultSet.TYPE_SCROLL_INSENSITIVE
                    , ResultSet.CONCUR_UPDATABLE);
                ResultSet rs = pstmt.executeQuery())
            {
                rs.last();
                int rowCount = rs.getRow();
                for (int i = rowCount; i > 0 ; i-- )
                {
                    rs.absolute(i);
                    System.out.println(rs.getString(1) + "	"
                        + rs.getString(2) + "	" + rs.getString(3));
                    // 修改记录指针所有记录、第2列的值
                    rs.updateString(2 , "学生名" + i);
                    // 提交修改
                    rs.updateRow();
                }
            }
        }
        public static void main(String[] args) throws Exception
        {
            ResultSetTest rt = new ResultSetTest();
            rt.initParam("mysql.ini");
            rt.query("select * from student_table");
        }
    }
    View Code


    处理Blob类型数据

    Blob(Binary Long object)是二进制长对象的意思。使用该类可以吧图片、声音等文件的二进制数据保存在数据库中,并可以从数据库中恢复指定文件。

    通过PrepareStatement的setBinaryStream(int parameterIndex,InputStream x),该方法可以指定参数传入二进制流。

    如果需要从ResultSet中取出Blob数据,可以调用ResultSet的getBlob(int columnIndex)来返回一个Blob对象,然后再通过Blob对象的getBinaryStream()方法获取该Blob数据的输入流,也可以使用Blob对象的getBytes()方法直接读取该Blob对象封装的二进制数据。

    使用ResultSetMetaData分析结果集:

    该对象可以通过ResultSet的getMetaData()方法来放回。常用的方法有:

    • int getColumnCount():返回该ResultSet的列数量
    • String getColumnName(int column):返回指定索引的列名
    • int getColumnType(int column):返回指定索引的列类型

    事务处理

     事务是由一步或几步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。

    事务有四个特性:原子性、一致性、隔离性、持续性。

    数据库事务由下列语句组成。

    一组DML语句,一条DDL语句,一条DCL语句。DDL和DCL语句最多只能有一条,因为DDL和DCL语句都会导致事务立即提交。

    事务提交方式(没有提交前事务中的语句不会生效)

    1.显式提交:使用commit

    2.自动提交:执行DDL或DCL语句,或者程序正常退出。

    事务回滚方式:(没有生效的事务可以回滚)

    1.显式回滚:使用rollback

    2.自动回滚:系统错误或者强行退出

    自动提交和开始事务是对立的,开始事务功能后,就会将自动提交的功能关闭。正常情况下需要手动关闭自动提交。

    JDBC对事务的支持

    可以调用Connection的setAutoCommit()方法来关闭自动提交,开启事务。getAutoCommit()返回自动提交模式。commit()提交事务。rollback()回滚事务。

    例子:

    import java.sql.*;
    import java.io.*;
    import java.util.*;
    
    public class TransactionTest
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void insertInTransaction(String[] sqls) throws Exception
        {
            // 加载驱动
            Class.forName(driver);
            try(
                Connection conn = DriverManager.getConnection(url , user , pass))
            {
                // 关闭自动提交,开启事务
                conn.setAutoCommit(false);
                try(
                    // 使用Connection来创建一个Statment对象
                    Statement stmt = conn.createStatement())
                {
                    // 循环多次执行SQL语句
                    for (String sql : sqls)
                    {
                        stmt.executeUpdate(sql);
                    }
                }
                // 提交事务
                conn.commit();
            }
        }
        public static void main(String[] args) throws Exception
        {
            TransactionTest tt = new TransactionTest();
            tt.initParam("mysql.ini");
            String[] sqls = new String[]{
                "insert into student_table values(null , 'aaa' ,1)",
                "insert into student_table values(null , 'bbb' ,1)",
                "insert into student_table values(null , 'ccc' ,1)",
                // 下面这条SQL语句将会违反外键约束,
                // 因为teacher_table中没有ID为5的记录。
                "insert into student_table values(null , 'ccc' ,5)" //
            };
            tt.insertInTransaction(sqls);
        }
    }
    View Code

    使用DatabaseMetaData分析数据库信息

    通过Connection提供的getMetaData()方法获取DatabaseMetaData对象。许多DatabaseMetaData方法是以ResultSet对象的形式返回查询信息,然后使用ResultSet中的常规方法获取内容。如果没有内容就返回一个空的ResultSet对象。

    DatabaseMetaData的许多方法都需要传入一个xxxPattern模式字符串,这里的xxxPattern不是正则表达式,而是SQL里的模式字符串。

    即用百分号(%)代表任意多个字符,使用下划线(_)代表一个字符。通常情况下,如果把该模式字符串的参数值设置为null,即表明该参数不过为过滤条件。

    例子:

    import java.sql.*;
    import java.util.*;
    import java.io.*;
    
    public class DatabaseMetaDataTest
    {
        private String driver;
        private String url;
        private String user;
        private String pass;
        public void initParam(String paramFile)throws Exception
        {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
        public void info() throws Exception
        {
            // 加载驱动
            Class.forName(driver);
            try(
                // 获取数据库连接
                Connection conn = DriverManager.getConnection(url
                    , user , pass))
            {
                // 获取的DatabaseMetaData对象
                DatabaseMetaData dbmd = conn.getMetaData();
                // 获取MySQL支持的所有表类型
                ResultSet rs = dbmd.getTableTypes();
                System.out.println("--MySQL支持的表类型信息--");
                printResultSet(rs);
                // 获取当前数据库的全部数据表
                rs = dbmd.getTables(null,null, "%" , new String[]{"TABLE"});
                System.out.println("--当前数据库里的数据表信息--");
                printResultSet(rs);
                // 获取student_table表的主键
                rs = dbmd.getPrimaryKeys(null , null, "student_table");
                System.out.println("--student_table表的主键信息--");
                printResultSet(rs);
                // 获取当前数据库的全部存储过程
                rs = dbmd.getProcedures(null , null, "%");
                System.out.println("--当前数据库里的存储过程信息--");
                printResultSet(rs);
                // 获取teacher_table表和student_table之间的外键约束
                rs = dbmd.getCrossReference(null,null, "teacher_table"
                    , null, null, "student_table");
                System.out.println("--teacher_table表和student_table之间"
                    + "的外键约束--");
                printResultSet(rs);
                // 获取student_table表的全部数据列
                rs = dbmd.getColumns(null, null, "student_table", "%");
                System.out.println("--student_table表的全部数据列--");
                printResultSet(rs);
            }
        }
        public void printResultSet(ResultSet rs)throws SQLException
        {
            ResultSetMetaData rsmd = rs.getMetaData();
            // 打印ResultSet的所有列标题
            for (int i = 0 ; i < rsmd.getColumnCount() ; i++ )
            {
                System.out.print(rsmd.getColumnName(i + 1) + "	");
            }
            System.out.print("
    ");
            // 打印ResultSet里的全部数据
            while (rs.next())
            {
                for (int i = 0; i < rsmd.getColumnCount() ; i++ )
                {
                    System.out.print(rs.getString(i + 1) + "	");
                }
                System.out.print("
    ");
            }
            rs.close();
        }
        public static void main(String[] args)
            throws Exception
        {
            DatabaseMetaDataTest dt = new DatabaseMetaDataTest();
            dt.initParam("mysql.ini");
            dt.info();
        }
    }
    View Code
  • 相关阅读:
    全方位讲解 Nebula Graph 索引原理和使用
    一首古诗带来的图数据库大冒险
    Nebula Graph 在众安保险的图实践
    springioc源码
    leetcode原地删除系列283移除0
    leetcode21单链表问题
    20天备考初级会计
    leetcode原地删除系列27
    leetcode 在排序数组中查找元素的第一个和最后一个位置
    内置后置处理器要理解的问题
  • 原文地址:https://www.cnblogs.com/moonpool/p/5559294.html
Copyright © 2020-2023  润新知