jdbc

JDBC介绍
    使用java 操作数据库的规范(接口)
    驱动,数据库生产厂商提供JDBC规范的实现,使用时需要导入驱动包jar
        mysql驱动类名称:mysql-connector-java-5.1.22-bin.jar
    编写流程
        1 注册驱动
        2 获得链接
        3 获得语句执行者
        4 执行sql语句
        5 处理结果
        6 释放资源
    注意
        jdbc开发接口编程,包:java.sql 和 javax.sql



JDBC编写流程
    1 注册驱动:Class.forName(驱动名称);
    2 获得链接:Connection conn = DriverManager.getConnection(url,用户,密码);
    3 获得语句执行者:Statement st = conn.createStatement();
    4 执行语句:
        DML:int r = st.executeUpdate(sql );        //返回影响行数
        DQL: ResutlSet rs = st.executeQuery(sql);   //返回结果集
    5 处理结果
        遍历:rs.next() --> 向下移动,如果有记录返回true
            获得数据:rs.getXxx(字段名称)   //Xxx为类型
    6 释放资源
        rs.close();
        st.close();
        conn.close();
    注意:Statement存在sql注入问题,应使用PreparedStatement对象
    示例
        更新
            // 1 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2 获得链接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10", "root", "1234");
            // 3 获得语句执行者
            Statement st = conn.createStatement();
            // 4 执行sql语句
            int r = st.executeUpdate("insert into users(id,firstname,secondname,age,count) values('u008','jack','1234',89,150)");   //执行更新DML语句
            // 5 处理结果
            System.out.println(r);
            // 6 释放资源
            st.close();
            conn.close();
        查询
            // 1 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2 获得链接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10", "root", "1234");
            // 3 获得语句执行者
            Statement st = conn.createStatement();
            // 4 执行sql语句--查询
            ResultSet rs = st.executeQuery("select * from users");
            // 5 处理结果
            while(rs.next()){
                // 5.1 通过rs.getXxx(字段) 获得指定“字段名称”的值 , getString -- varchar() ;  getInt  -- int()
                String id = rs.getString("id");
                String firstname = rs.getString("firstname");
                String secondname = rs.getString("secondname");
                int age = rs.getInt("age");
                int count = rs.getInt("count");
                String classes = rs.getString("classes");
                
                System.out.println(id + " , "  + firstname  + " , " + secondname + " , " + age + " , " + count + " , " + classes );
            }
            // 6 释放资源
            rs.close();
            st.close();
            conn.close();



数据库的驱动名称和连接url
    mssql
        驱动名称    com.microsoft.sqlserver.jdbc.SQLServerDriver
        连接url     jdbc:sqlserver://localhost:1433;DatabaseName=数据库名
    mysql
        驱动名称    com.mysql.jdbc.Driver
        连接url     jdbc:mysql://localhost:3306/数据库名
    oracle
        驱动名称    oracle.jdbc.OracleDriver
        连接url     jdbc:oracle:thin:@localhost:1521:数据库名
    注意
        连接url中的协议的格式   协议:子协议:子名称
        mysql省略写法
            jdbc:mysql://localhost:3306/db_name
            localhost默认,3306默认  --> jdbc:mysql:///db_name
        odbc方式连接数据库
            odbc通过统一接口连接数据库,无需jar包,但速度慢
            先配置数据源,控制面板-->管理工具-->Odbc数据源
            驱动名称    sun.jdbc.odbc.JdbcOdbcDriver
            连接url     Jdbc:odbc:数据源名



DriverManager类(java.sql)
    概述
        管理一组 JDBC 驱动程序的基本服务。(管理JDBC驱动)
    常用方法
        static void registerDriver(Driver driver) 
            向 DriverManager 注册给定驱动程序。 
        static Connection getConnection(String url, String user, String password) 
            试图建立到给定数据库 URL 的连接。 
    说明
        驱动:JDBC规范规定每一个驱动程序,必须实现接口java.sql.Driver
        注册驱动:Class.forName("com.mysql.jdbc.Driver")
        实质是执行指定类静态代码块中的代码进行注册
            java.sql.DriverManager.registerDriver(new Driver()); 

        

Connection接口(java.sql)
    概述
        与特定数据库的连接(会话)。注:默认情况下,Connection 在执行每个语句后都会自动提交更改
    常用方法
        void close() 
            立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。 
        Statement createStatement() 
            创建一个 Statement 对象来将 SQL 语句发送到数据库。
        CallableStatement prepareCall(String sql) 
            创建一个 CallableStatement 对象来调用数据库存储过程。 
        PreparedStatement prepareStatement(String sql) 
            创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。 
    事务相关方法
        void commit() 
            使自从上一次提交/回滚以来进行的所有更改成为持久更改。 
        boolean getAutoCommit() 
            检索此 Connection 对象的当前自动提交模式。 
        void rollback() 
            取消在当前事务中进行的所有更改,并释放此 Connection 对象当前保存的所有数据库锁定。
        void rollback(Savepoint savepoint) 
            取消设置给定 Savepoint 对象之后进行的所有更改。 
        void setAutoCommit(boolean autoCommit) 
            将此连接的自动提交模式设置为给定状态。 
        Savepoint setSavepoint(String name) 
            在当前事务中创建一个具有给定名称的保存点,并返回表示它的新 Savepoint 对象。
    其它方法
        Statement createStatement(int resultSetType, int resultSetConcurrency) 
            创建一个 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
        PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) 
            创建一个 PreparedStatement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。 
        说明
            resultSetType:结果集类型。
                ResultSet.TYPE_FORWARD_ONLY:光标(游标)只能向前移动(rs.next)
                ResultSet.TYPE_SCROLL_INSENSITIVE:可滚动,如果ResultSet中的数据进行了修改不能同步到数据库
                ResultSet.TYPE_SCROLL_SENSITIVE:可滚动,如果ResultSet中的数据进行了修改,可以同步到数据库
            resultSetConcurrency:并发类型
                ResultSet.CONCUR_READ_ONLY:不可以更新(只读)
                ResultSet.CONCUR_UPDATABLE:可以更新



Statement接口(java.sql)
    概述
        用于执行静态 SQL 语句并返回它所生成结果的对象。
    常用方法
        void addBatch(String sql) 
            将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中。 
        void close() 
            立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。 
        boolean execute(String sql) 
            执行给定的 SQL 语句,该语句可能返回多个结果。 如果结果为true,可使用getResultSet获得结果集;如果结果为false,可使用getUpdateCount获得影响行数
        int[] executeBatch() 
          将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。 
        ResultSet executeQuery(String sql) 
            执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。 
        int executeUpdate(String sql) 
            执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。 
        Connection getConnection() 
            检索生成此 Statement 对象的 Connection 对象。 
        int getMaxRows() 
            检索由此 Statement 对象生成的 ResultSet 对象可以包含的最大行数。 
        ResultSet getResultSet() 
            以 ResultSet 对象的形式检索当前结果。 
        int getUpdateCount() 
            以更新计数的形式检索当前结果;如果结果为 ResultSet 对象或没有更多结果,则返回 -1。



SQL注入
    概述
        用户填写的内容,作为了sql语句的语法的一部分。
            例如:
                用户名填写 jack ' or 1=1 or 1=' 则可以绕过密码检测,如果存在名叫jack的用户,就可以登陆成功
                ' 破坏式注入,如果程序存在注入问题,则使用一个单引号可以使程序报错
    解决
        Statement对象存在sql注入问题
        PreparedStatement预处理对象,预先编译sql语句,参数不会作为sql语法的一部分
    对比
        Statement,sql语句和参数都是程序员自己编写时可以使用,执行速度较快。
        PreparedStatement,参数由用户输入时使用,大量执行某条固定语法的sql语句时也可使用。


    
PreparedStatement接口(java.sql)
    概述
        表示预编译的 SQL 语句的对象。 
        SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。
    常用方法
        void addBatch() 
            将一组参数添加到此 PreparedStatement 对象的批处理命令中。 
        void clearParameters() 
            立即清除当前所有参数值。 
        boolean execute() 
            在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。 
        int[] executeBatch() 
          将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。 
        ResultSet executeQuery() 
            在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。 
        int executeUpdate() 
            在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL INSERT、UPDATE 或 DELETE 语句;或者是一个什么都不返回的 SQL 语句,比如 DDL 语句。 
        void setObject(int parameterIndex, Object x) 
            使用给定对象设置指定参数的值。 这个方法还有各种重载方法,注意索引从1开始
    注意
        1 PreparedStatement接口继承于Statement接口,所以也存在executeQuery(String)方法,但是用了会报错
        2 获得预处理对象时,必须先提供sql语句。支持将实际参数使用?替换。数据库在预先编译sql语句时,不处理实际参数。
            例如:String sql = "select from t_user where username = ? and password = ?";
        3 在执行sql语句之前,需要用实际参数,替换回? 。此时实际参数就不是sql语句语法的一部分。
            例如:preparedStatement.setString(1,"张三"); //注意索引从1开始,第一个?就是1
    代码示例
        更新
            //2准备sql语句
            String sql = "insert into t_user(username,password) values(?,?)";
            //3 获得预处理对象
            psmt = conn.prepareStatement(sql);
            //4设置具体的实际参数
            psmt.setString(1, user.getUsername());
            psmt.setString(2, user.getPassword());
            //5执行sql语句
            int r = psmt.executeUpdate();
        查询
            //2准备sql语句
            String sql = "select * from t_user where username = ? and password = ?";
            //3 获得预处理对象
            PreparedStatement psmt = conn.prepareStatement(sql);
            //4 设置实际参数,并执行
            psmt.setString(1, username);
            psmt.setString(2, password);
            //5 处理结果
            ResultSet rs = psmt.executeQuery();
        关闭资源
            public static void close(Connection conn, Statement st, ResultSet re){
                //关闭ResultSet对象
                try{
                    if(re != null){
                        re.close();
                    }
                }catch(Exception e1){
                    System.out.println("关闭ResultSet对象异常");
                }finally{
                    //关闭Statement对象
                    try{
                        if(st != null){
                            st.close();
                        }
                    }catch(Exception e2){
                        System.out.println("关闭Statement对象异常");
                    }finally{
                        //关闭Connection对象
                        try{
                            if(conn != null){
                                conn.close();
                            }
                        }catch(Exception e3){
                            System.out.println("关闭Connection对象异常");
                        }
                    }
                }
            }



PreparedStatement应用
    应用场景
        防止SQL注入
        大数据处理
        批处理
        支持非字符串数据
    大数据处理
        mysql类型
            字节数据:blob (64k) 、mediumblob (16m) 、longblob (4g)
            字符数据:text (64k) 、mediumtext (16m) 、longtext (4g)
        java 类型
            字节数据:Blob,二进制大对象 (Binary Large Object)
            字符数据:Clob,字符大对象 (Character Large Object)
        存储图片
            数据库表的列类型为blob (64k) 或 mediumblob (16m) 或 longblob (4g)
            PreparedStatement设置参数时,使用下面的方法即可
                void setBinaryStream(int parameterIndex, InputStream x) 将指定参数设置为给定输入流。 
        存储大文本
            数据库表的列类型为text (64k) 或 mediumtext (16m) 或 longtext (4g)
        注意
            mysql的my.ini文件中可以通过 max_allowed_packet=32M 来设置可存储的数据包大小
    批处理
        一次执行多个操作
        Statement,一次可以执行不同的sql语句
            添加sql : addBatch(String sql) 
            执行批处理:int[] executeBatch() 
            注意:每一个sql语句都会被编译,再执行
        PreparedStatement,预先编译sql语句,批量处理不同的数据
            设置参数后保存参数:addBatch()
            执行批处理:executeBatch() 
        注意:
            mysql 对批处理的实现不好,速度较慢。Oracle速度很快。
    注意
        通常使用的java.util.Date,存储到数据库时要先转换为java.sql.Date.否则mssql报错
            new java.sql.Date(new java.util.Date().getTime());



事务
    参见<SQL>中的<事务>
    java 事务操作:
        开启事务:conn.setAutoCommit(false);    -->取消自动提交,mysql默认自动提交的
        提交事务:conn.commit();
        回滚事务:conn.rollback();   -->回滚到事务开始时
            rollback(Savepoint savepoint) 回滚到事务的保存点
            setSavepoint() 设置保存点
        事务处理格式:
            //#1 获得连接
            Connection conn = null;
            try {
                conn = ... 
                //#2 开启事务
                conn.setAutoCommit(false);
                
                //...操作
            
                //#3 提交事务
                if(操作1影响行数 >0 && 操作2影响行数>0){
                    conn.commit();
                }else{
                    //#4 回滚事务
                    conn.rollback();
                }
            } catch(Exception e){
                //#4 回滚事务
                conn.rollback();
            } finally{
                //#5释放资源
                conn.close();
            }



连接池
    思想
        大量建立与数据库的连接很耗时
        需要一个容器缓存连接
        当用户使用时,从容器移除,用户使用
        当用户使用完成后,不关闭,而是归还给容器.等待被下一次使用
        省去了与数据库建立连接的过程,提高了程序执行速度
    DataSource接口(javax.sql)
        数据源接口. 所有连接池需要实现此接口
        常用方法
            Connection getConnection() 从连接池中获得连接
    第三方
        dbcp : apache提供的
            jar
                核心jar:commons-dbcp-1.4.jar
                依赖jar:commons-pool-1.6.jar
            手动方式(非配置文件)
                核心类:BasicDataSource
                api
                    1 基本4项
                        setDriverClassName("com.mysql.jdbc.Driver");
                        setUrl("jdbc:mysql://localhost:3306/day12");
                        setUsername("root");
                        setPassword("1234");
                    2 其他项 --性能
                        // 最大活动数
                        dataSource.setMaxActive(50);
                        // 最大空闲数
                        dataSource.setMaxIdle(20);
                        // 最小空闲书
                        dataSource.setMinIdle(5);
                        // 初始化个数
                        dataSource.setInitialSize(10);
                    3. 获得连接
                        dataSource.getConnection();
            配置文件方式
                示例
                    配置文件src/dbcpConfig.properties内容(配置文件类型必须是properties,位置和名称任意)
                        #连接设置
                        driverClassName=com.mysql.jdbc.Driver
                        url=jdbc:mysql://localhost:3306/test
                        username=root
                        password=1234
                        #初始化连接
                        initialSize=5
                        #最大连接数量
                        maxActive=10
                        #最大空闲连接
                        maxIdle=5
                        #最小空闲连接
                        minIdle=3
                        #超时等待时间以毫秒为单位 1000毫秒/1000等于10秒
                        maxWait=10000
                        #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
                        #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
                        connectionProperties=useUnicode=true;characterEncoding=gbk
                        #指定由连接池所创建的连接的自动提交(auto-commit)状态。
                        defaultAutoCommit=true
                        #driver default 指定由连接池所创建的连接的只读(read-only)状态。
                        #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
                        defaultReadOnly=
                        #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
                        #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
                        defaultTransactionIsolation=READ_UNCOMMITTED
                    java代码
                        //连接池对象
                        private static DataSource dataSource;
                        static{
                            try {
                                //获得文件
                                InputStream is = DbcpJdbcUtils2.class.getClassLoader().getResourceAsStream("dbcpConfig.properties");
                                //关联配置文件
                                Properties properties = new Properties();
                                properties.load(is);
                                //获得数据源
                                dataSource = BasicDataSourceFactory.createDataSource(properties);
                            } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException(e);
                            }
                        }
                        /**
                         * 返回连接
                         * @return
                         */
                        public static Connection getConnection(){
                            try {
                                return dataSource.getConnection();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }
        c3p0
            jar
                核心jar:c3p0-0.9.2-pre5.jar
                依赖jar:mchange-commons-java-0.2.3.jar
            XML配置文件方式
                示例
                    配置文件src/c3p0-config.xml内容(配置文件位置,名称固定,程序会自动读取)
                        <c3p0-config>
                            <!-- 命名的配置 -->
                            <named-config name="shiyan">
                                <property name="driverClass">com.mysql.jdbc.Driver</property>
                                <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test</property>
                                <property name="user">root</property>
                                <property name="password">1234</property>
                                <!-- 如果池中数据连接不够时一次增长多少个 -->
                                <property name="acquireIncrement">5</property>
                                <property name="initialPoolSize">5</property>
                                <property name="minPoolSize">3</property>
                                <property name="maxPoolSize">5</property><!-- 最大连接数 -->
                                <property name="maxStatements">0</property>
                                <property name="maxStatementsPerConnection">5</property>
                            </named-config>
                        </c3p0-config>
                    java代码
                        public class C3p0JdbcUtils2 {
                            //连接池对象(参数为xml文件中named-config的name属性)
                            private static ComboPooledDataSource dataSource = new ComboPooledDataSource("shiyan");
                            /**
                             * 返回连接
                             * @return
                             */
                            public static Connection getConnection(){
                                try {
                                    return dataSource.getConnection();
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
    自定义连接池
        实现接口,javax.sql.DataSource (数据源) --> getConnection()
        思想
            1 创建一个池 (容器),放置若干连接
            2 获得连接,从池中移除。缺点:需要实现接口的所有方法,如果方法操作繁琐。
            3 使用完成之后,将连接归还连接池。
        代码示例
            public class JdbcUtils {
                //模拟连接池(链表结构的集合)
                public static LinkedList<Connection> list = new LinkedList<Connection>();
                static{
                    //向连接池添加多个连接
                    try {
                        Class.forName("com.mysql.jdbc.Driver");
                        for (int i = 0; i < 3; i++) {
                            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
                            list.add(conn);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                /**
                 * 返回连接
                 * @return
                 */
                public static synchronized Connection getConnection(){
                    //同步方法 防止线程并发性问题
                    while(list.size() == 0){//没有连接就等待
                        try{
                            Thread.sleep(100);
                        }catch(Exception e){
                        }
                    }
                    return list.removeFirst();//返回连接,并从连接池中移除连接
                }
                /**
                 * 关闭连接
                 * @param conn
                 */
                public static void close(Connection conn){
                    list.add(conn);//将连接添加到连接池
                }
            }
            注意:需要使用动态代理对Connection对象的close方法进行方法增强,防止用户手动关闭.(我懒,这里没写)



DBUtils工具包
    简化JDBC的工具包
    核心jar:/dbutils/commons-dbutils-1.4.jar
    提供数据源
        核心类:QueryRunner
            构造方法:QueryRunner(DataSource ds) ,需要提供数据源,工具内部自动获得连接,自动释放资源
            api
                操作DML
                    int update(String sql)  , 执行DML语句,但没有参数
                    int update(String sql, Object param)  , 执行DML语句,有一个参数
                    int update(String sql, Object... params)  , 执行DML语句,多个参数
                操作DQL
                    <T> T  query(String sql, ResultSetHandler<T> rsh) ,执行没有参数的sql语句,并使用结果集处理类进行处理,生产指定的对象。
                    <T> T  query(String sql, ResultSetHandler<T> rsh, Object... params) 执行多个参数的sql语句,并使用结果集处理类进行处理,生产指定的对象。
                    处理类
                        BeanHandler ,将查询的一个结果,封装到指定的JavaBean对象中。
                        BeanListHandler ,将查询的所有结果的每一个结果先封装到JavaBean中,再将javaBean添加List集合中。
                        ScalarHandler,查询一行一列数据,处理聚合函数。(count/sum/max/min/avg)
    手动维护连接(了解--一般在使用事务时)
        核心类:QueryRunner
            构造方法:QueryRunner()  ,工具不在自动维护连接,需要自己再执行时使用连接。
            api
                操作DML
                    int update(Connection conn, String sql)  ,在指定连接时, 执行DML语句,但没有参数
                    int update(Connection conn, String sql, Object param)  , 在指定连接时,执行DML语句,有一个参数
                    int update(Connection conn, String sql, Object... params)  , 在指定连接时,执行DML语句,多个参数
                操作DQL
                    <T> T  query(Connection conn,String sql, ResultSetHandler<T> rsh) ,
                        在指定连接时, 执行没有参数的sql语句,并使用结果集处理类进行处理,生产指定的对象。
                    <T> T  query(Connection conn,String sql, ResultSetHandler<T> rsh, Object... params) 
                        在指定连接时, 执行多个参数的sql语句,并使用结果集处理类进行处理,生产指定的对象。



BeanUtils工具包
    将指定内容封装到JavaBean一个工具类
    jar
        核心jar:commons-beanutils-1.8.3.jar
        依赖jar:commons-logging-1.1.1.jar
    核心类:
        BeanUtils
            static setProperty(Object bean, String name, Object value) 给指定的javabean bean 的指定属性name,进行设置值value
            static populate(Object bean, Map properties) ,将Map所有的数据封装到javabean中,map的key就是javabean的属性
                Map<String,String[]> request.getParameterMap()
                    key : string ,对应javabean的属性
                    value :string[] ,表单提交的所有的值
    时间转换
        在调用api前设置
            DateConverter converter = new DateConverter();
            converter.setPattern("yyyy-MM-dd");
            ConvertUtils.register(converter,Date.class);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值