JDBC

问题总结

1. 获取连接的时候 

 java.sql.SQLException: java.lang.VerifyError: (class: com/mysql/jdbc/DatabaseMetaData, method: supportsRefCursors signature: ()Z) Illegal use of nonvirtual function call 
时候 重装jdk

2.


JDBC:

java操作数据库.jdbc是oracle公司指定的一套规范(一套接口)

驱动:jdbc的实现类.由数据库厂商提供.

我们就可以通过一套规范操作不同的数据库了(多态)

jdbc作用:

连接数据库   Connection

发送sql语句  Statement

处理结果       ResultSet



使用


步骤


准备

数据库和表,,,,,,创建一个项目,,,,,,导入驱动jar包

编码


注册驱动
获取连接
编写sql
创建预编译的语句执行者
设置参数
执行sql
处理结果
释放资源

驱动注册问题

        try {
            // 注册驱动,注册两次 : com.mysql.jdbc.Driver的静态代码块里调用相同注册方法
            java.sql.DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        } catch (SQLException e) {
            e.printStackTrace();
        }

加载将类加载到内存中即可:

        Class.forName("com.mysql.jdbc.Driver");// 包名+类名
        Class clazzClass = com.mysql.jdbc.Driver.class;
        Class clazzClass2 = (new com.mysql.jdbc.Driver()).getClass();


配置文件

    static {
        try {
            // 读取配置文件
            InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            // InputStream is = JdbcUtil.class.getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(is);
            // jdbc:mysql://localhost:3306/school
            url = prop.getProperty("url");
            username = prop.getProperty("username");
            password = prop.getProperty("password");
            // com.mysql.jdbc.Driver
            String driverClass = prop.getProperty("driverClass");
            Class.forName(driverClass);

        } catch (Exception e) {
            // 只能抓取
            throw new ExceptionInInitializerError(e);
        }
    }


SQL注入问题(statement)

            /** 第三步:语句执行者 **/
            String username = "aaaa"; 
            String pwd = "bb or 1=1 or 1='1";// 恒成立
            String sql = "select * from tb_student where username='" + username + "' and password='" + pwd+"'";
            Statement stmt = connection.createStatement();// sql注入问题
正解:

            /** 第一步:注册驱动 **/
            Class.forName("com.mysql.jdbc.Driver");
            /** 第二步:获取连接 **/
            // 协议:数据库类型:子协议 参数:数据库类型,,哪个数据库
            String url = "jdbc:mysql://localhost:3306/school"; // http://localhost:80/xx.html   简写:jdbc:mysql:///school
            String user = "root";
            String password = "1234";
            Connection connection = java.sql.DriverManager.getConnection(url, user, password);
            /** 第三步:预编译的语句执行者 **/
            String sql = "select * from tb_student where username=? and password=?";
            PreparedStatement pstmt = connection.prepareStatement(sql); 
            /** 第四步:设置参数 **/
            pstmt.setString(1, "root");
            pstmt.setString(2, "1234");
            /** 第五步:执行 **/
            ResultSet resultSet = pstmt.executeQuery(sql);不能传sql参数 ,如果传了就是调用stmt的方法了!!! pstmt.executeUpdate();
            /** 第刘步:数据处理 **/
            while (resultSet.next()) {
                String string = resultSet.getString("name");
                System.out.println(string);
            }

关闭连接

            if (resultSet != null)
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    // e.printStackTrace(); ignore
                } finally {
                    resultSet = null;
                }

            if (pstmt != null)
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    // e.printStackTrace(); ignore
                } finally {
                    pstmt = null;
                }

            if (connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    // e.printStackTrace();
                    // ignore
                } finally {
                    connection = null;
                }

常用类

DriverManager:管理了一组jdbc的操作 类   

static Connection getConnection(String url, String user, String password) //获取连接

Connection:连接 接口

Statement createStatement() : //获取普通的语句执行者 会出现sql注入问题

	PreparedStatement prepareStatement(String sql) ://获取预编译语句执行者 !!
	CallableStatement prepareCall(String sql)://获取调用存储过程的语句执行者

    setAutoCommit(false) //手动开启事务
    rollback()//事务回滚
    commit()//提交事务,关闭自动提交,不提交,所有操作都不无效
    SavePoint conn.setSavepoint(); //获得回滚点
    rollback(savePoint)//事务回滚,回滚点前的sql还有效

Statement:语句执行者 接口

setXxx(int 第几个问号,Object 实际参数);

resultSet executeQuery() ://执行 r 语句 返回值:结果集
int executeUpdate() ://执行cud 语句 返回值:影响的行数

            addBatch(sql);//批处理
            executeBatch();


事务隔离级别

             问题:
            1.脏读:一个事务读另外一个正在进行的事务,另一个可能回滚
            2.不可重复读:一个事务多次查询中,另一个事务提交了修改,导致多次查询结果不一样
            3.幻读(虚读):一个事务多次查询中,另一个事务提交了插入,删除,,多次查询条数不一样

            
             /** 
             * Connection.TRANSACTION_READ_UNCOMMITTED  读未提交数据,什么都不能避免
             * Connection.TRANSACTION_READ_COMMITTED  读提交后的数据,避免脏读
             * Connection.TRANSACTION_REPEATABLE_READ  可重读  ,避免脏读和不可重复读
             * Connection.TRANSACTION_SERIALIZABLE 序列化同步(最高级别,等待,单线程),都避免
             */
            connection.setAutoCommit(false);//开启事务
            connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);


ResultSet:结果集 接口

boolean next():判断是否有下一条记录,若有返回true且将光标移到下一行,若没有呢则返回false

getXxx(int|string)
            若参数为int :第几列
            若参数为string:列名(字段名)


 

            // java->sql 父类 -> 子类 ; 相反 子类->父类 直接赋值
            Date date = new java.util.Date(); // 父类
            java.sql.Date date2 = new java.sql.Date(date.getTime());


数据库连接

使用jdbc的时候,每操作一次都需要获取连接(创建)用完之后把连接释放掉了(销毁).

连接池初始化时候,存入一定数量的连接,用的时候通过方法获取,不用的时候归还.减少创建,效果的消耗


试:

1.继承或实现   (Connection有数据库厂商实现或继承,不可通)

2.装饰者模式(静态代理)

3.动态代理

装饰者模式

		1.装饰者和被装饰者实现同一个接口或者继承同一个类
		2.装饰者中要有被装饰者的引用
		3.对需要增强的方法进行加强
		4.对不需要加强的所有方法调用原来方

动态代理

任何一个接口实现类都可以定义一个代理类(仅支持interface代理)
代理者和被者实现同一个或多个接口
代理对象,,,依旧是被代理对象
代理类中要有被代理类的引用,需要被代理对象,干活!!!

         Student sProxy = (Student) java.lang.reflect.Proxy.newProxyInstance(loader, interfaces, h);
         loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载(一般是)
         interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
         h:  一个InvocationHandler接口的对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

        final Student s = new Student();// 被代理对象,,,最好配置文件加载(插卡) Class.forName("").newInstance();
        Student sProxy = (Student) java.lang.reflect.Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass()
                .getInterfaces(), new InvocationHandler() {
            // proxy:  指代我们所代理的那个真实对象
            // method:  指代的是我们所要调用真实对象的某个方法的Method对象
            // args:  指代的是调用真实对象某个方法时接受的参数
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                String name = method.getName();
                Object invoke = method.invoke(s, args);
                return invoke;
            }
        });


数据库连接池  

所有的连接池必须实现一个接口 javax.sql.DataSource接口

获取连接方法:Connection getConnection() 


DataSource

        1.导入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.jar)
        2.使用api
            a.硬编码
                //创建连接池
                BasicDataSource ds = new BasicDataSource();
                
                //配置信息
                ds.setDriverClassName("com.mysql.jdbc.Driver");
                ds.setUrl("jdbc:mysql:///day07");
                ds.setUsername("root");
                ds.setPassword("1234");
            b.配置文件
                实现编写一个properties文件
                //存放配置文件
                Properties prop = new Properties();
                prop.load(getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
                //设置
                //prop.setProperty("driverClassName", "com.mysql.jdbc.Driver");
                
                //创建连接池
                DataSource ds = new BasicDataSourceFactory().createDataSource(prop);



c3p0

http://www.mchange.com/projects/c3p0/

        C3P0:
        hibernate和spring使用
        有自动回收空闲连接的功能.
        使用步骤:
            1.导入jar包(c3p0-0.9.5.2.jar和mchange-commons-java-0.2.11.jar)
            2.使用api 
                a.硬编码(不推荐)
                    new ComboPooledDataSource()
                b.配置文件
                    配置文件的名称:c3p0.properties 或者 c3p0-config.xml
                    配置文件的路径:src下
                
                    编码只需要一句话
                        new ComboPooledDataSource()//使用默认的配置
                        new ComboPooledDataSource(String configName)//使用命名的配置 若配置的名字

c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/xxx
c3p0.user=root
c3p0.password=1234


DbUtils

http://commons.apache.org/proper/commons-dbutils/ 







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值