JAVA基础(27)-JAVA JDBC

一、介紹

         Java DataBase Connectivity--java数据库连接技术,简称JDBC,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成。 同时,也是一个“低级”接口,在其之上可以使用“高级”接口,更方便的连接数据库。

    原理
        JDBC负责提供接口数据库厂商使用自己数据库的特点来实现接口。      程序员调用接口,实际上底层调用数据库厂商实现的部门实际工作过程,編寫類之前要引入jar包,在工程的目录下创建一个lib文件夹用来存放jar包

  1. 加载驱动,建立连接
  2. 获取Sql语句执行对象 
  3. 执行SQl语句
  4. 处理结果集
  5. 关闭连接  

二、接口与类型

        驱动管理类型:DriverManager
            static Connection getConnection(url,user,password)    通过地址,数据库用户名,用户密码 获取连接对象
        连接接口:Connection
            Statement createStatement()    获取一个SQL语句编译对象
            PreparedStatement  prepareStatement(String sql)    获取一个SQL语句预编译对象(可防止一些sql注入)
        SQL语句对象接口:
            Statement 用于编译静态SQL语句(编译多次)。
                  boolean execute(String sql)    用来执行DDL语言
                  ResultSet executeQuery(String sql)    用于执行DQL语言
                  int executeUpdate(String sql)    用于执行DML语言
                  void addBatch(String sql)    添加批处理
                  int[] executeBatch()    执行批处理
            PreparedStatement 用于编译静态SQL语句,是Statement的一个子类型,执行效率比Statement要高(只编译一次)
                  boolean  execute()    用来执行DDL语言
                  ResultSet executeQuery()    用来执行DQL语言
                  int executeUpdate()    用于执行DML语言
                 void addBatch()    添加批处理
                 int[] executeBatch()    执行批处理
        结果集接口:ResultSet 在进行DQL操作时, 将查询的所有记录信息封装到ResultSet对象中 .
                 boolean next()   询问结果集对象中是否有下一行记录。如果返回true,光标会自动移到下一行。    
                 还提供了一些数据库类型转java数据类型的方法:
                  int getInt(int columnIndex)/getInt(String columnName)
                 double getDouble(int columnIndex)/getDouble(String columnName)
                 String getString(int columnIndex)/getString(String columnName)
                 Date getDate(int columnIndex)/getDate(String columnName)

三、工具类的封装DBUtil

        每次連接數據庫時都需要加载驱动,建立链接。其中的参数我们书写的次数比较多。   
        方法1:为了方便,为了节省资源,我们可以使用静态块来加载驱动,将参数值当成类的静态属性进行封装。 (加载一次就可以)  
        方法2:使用Properties 读取配置文件里的信息(将可能需要改变的信息存储在配置文件中)
方法2代碼:

public class DBUtil {

    private static String drive;
    private static String url;
    private static String user;
    private static String pass;

    static {
        try {
            InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");

            Properties prop = new Properties();

            prop.load(is);

            drive = prop.getProperty("driver");
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            pass = prop.getProperty("pass");

            Class.forName(drive);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 連接數據庫
     */
    public static Connection getConnection() throws SQLException {

        return DriverManager.getConnection(url, user, pass);

    }

    /**
     * 關閉連接
     */
    public static void closeConnection(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试连接是否成功
     */
    public static void main(String[] args) {

        Connection conn = null;
        try {
            conn = DBUtil.getConnection();
            System.out.println(conn);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeConnection(conn);
        }
    }
}

配置文件(配置文件db.properties内容是MySQL和Oracle的):

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bd1802
user=root
pass=123456


#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:xe
#user=scott
#pass=tijer

异常

        jdbc发生的异常一般都是SQLException或者是其子类异常是检查性异常。    使用try-catch机制处理一下。finally里通常用来进行关闭数据库操作。

四、PreparedStatement的用法

        在使用Statement时,因为Statement会对静态SQL语句进行编译。有可能会改变SQL语句的结构。因此有SQL注入安全隐患。(SQL注入参考:=======================================)

        用法:可以对静态SQL语句使用问号"?"充当占位符。
            如:  select * from login_info where login_user = ? and login_pwd= ?

            使用此类中提供的类型转换方法进行给问号赋值

ps.setInt(int parameterIndex,int value)
ps.setDouble(int parameterIndex,double value)
ps.setString(int parameterIndex,String value)
ps.setDate(int parameterIndex,Date value)

五、批处理

JDBC对事务的支持

        事务要满足四个条件:ACID
               原子性:一个事务,要么成功,要么回滚(撤回)
               一致性:事务开始前的数据要和结束后的数据保持一致。
               隔离性:一个事务正在进行,另外的事务要等待。
               持久性:事务提交后,数据的改变是永久性的。
      
        JDBC对DML语言的操作是默认提交的。当有多个DML操作时,我们应该取消自动提交 。改为手动提交 
      
        Connection接口提供了一个方法
        void setAutoCommit(boolean flag)    true:表示自动提交,false:表示取消自动提交
        void commit()   提交事务
        void rollback()  事务回滚

批处理

        在进行插入数据操作时,有的时候,一条一条的操作,比较耗时。我们可以进行批量的插入操作。在进行批处理是要把自动提交关闭,改为手动提交

Statement:addBatch(String sql)
                  executeBatch():
PreparedStatement:addBatch():
                                executeBatch():

练习代码:

public class TestBatch {
    @Test
    public void testStatement02() {
        try {
            Statement stat = conn.createStatement();
            conn.setAutoCommit(false);
            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                String account_idcard = 1000000000000000l + (long) ((Math.random()) * 9000000000000000l) + "";
                String phone = 10000000000l + (long) ((Math.random()) * 90000000000l) + "";
                String sql = "insert into account_info values(null,'" + account_idcard + "','" + 12345 + "'," + 10 + ",'" + phone + "')";

                //添加批處理
                stat.addBatch(sql);
                if (i % 220 == 0) {
                    //執行一次批處理
                    stat.executeBatch();
                    conn.commit();
                }
            }
            //將不滿220條的再次執行
            stat.executeBatch();
            conn.commit();

            System.out.println("Statement02--1000次循環時間" + (System.currentTimeMillis() - start));
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testPreparedStatement02() {

        try {
            long start = System.currentTimeMillis();

            String sql = "insert into account_info values(null,?,'" + 12345 + "'," + 10 + ",?)";
            PreparedStatement pr = conn.prepareStatement(sql);

            conn.setAutoCommit(false);

            for (int i = 0; i < 5000; i++) {
                String account_idcard = 1000000000000000l + (long) ((Math.random()) * 9000000000000000l) + "";
                String phone = 10000000000l + (long) ((Math.random()) * 90000000000l) + "";

                pr.setString(1, account_idcard);
                pr.setString(2, phone);
                pr.addBatch();
                if (i % 220 == 0) {
                    pr.executeBatch();
                    conn.commit();
                }

            }
            pr.executeBatch();
            conn.commit();

            System.out.println("PreparedStatement02--1000次循環時間" + (System.currentTimeMillis() - start));
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testStatement01() {
        try {
            Statement stat = conn.createStatement();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 10000; i++) {
                String account_idcard = 1000000000000000l + (long) ((Math.random()) * 9000000000000000l) + "";
                String phone = 10000000000l + (long) ((Math.random()) * 90000000000l) + "";
                String sql = "insert into account_info values(null,'" + account_idcard + "','" + 12345 + "'," + 10 + ",'" + phone + "')";

                stat.executeUpdate(sql);
            }
            System.out.println("Statement--1000次循環時間" + (System.currentTimeMillis() - start));

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testPreparedStatement01() {
        try {
            long start = System.currentTimeMillis();

            String sql = "insert into account_info values(null,?,'" + 12345 + "'," + 10 + ",?)";
            PreparedStatement pr = conn.prepareStatement(sql);

            conn.setAutoCommit(false);


            for (int i = 0; i < 10000; i++) {
                String account_idcard = 1000000000000000l + (long) ((Math.random()) * 9000000000000000l) + "";
                String phone = 10000000000l + (long) ((Math.random()) * 90000000000l) + "";

                pr.setString(1, account_idcard);
                pr.setString(2, phone);
                pr.executeUpdate();

            }
            conn.commit();
            System.out.println("PreparedStatement--1000次循環時間" + (System.currentTimeMillis() - start));
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    private Connection conn;

    @Before
    public void connectionDatabase() {
        try {

            conn = DBUtil.getConnection();
        } catch (Exception e) {

        }
    }

}

猜你喜欢

转载自blog.csdn.net/woainiqazwsx123/article/details/82707350
今日推荐