【我的javaEE学习】JDBC简单入门

一、JDBC简介

1、JDBC是SUN公司为了简化操作数据推出一套规范。数据库厂商的驱动就是对JDBC的实现

2、Java Data Base Connectivity(java数据库连接),它主要由接口组成。

java.sql.*    javax.sql.*   JDK中数据库的驱动jar包

二、JDBC的编码步骤

前提:拷贝数据库的驱动到构建路径中(classpath)

1、注册驱动

2、获取与数据库的链接

3、创建代表SQL语句的对象

4、执行SQL语句

5、如果是查询语句,需要遍历结果集

6、释放占用的资源

三、JDBC中常用的接口详解

1、DriverManager作用

   ⑴注册驱动:

       方式一(不建议使用):DriverManager.registerDriver(new com.mysql.jdbc.Driver());

         原因:①依赖具体驱动。②导致驱动注册2遍,从源码里看(如下图)。

         

       方式二(建议):Class.forName("com.mysql.jdbc.Driver");

        只依赖字符串,可以实现运行时依赖,不用编码依赖(如下图)。

        

   ⑵获取与数据库的链接

        url:SUN和数据库厂商间的协议。

               MySql:jdbc:mysql://localhost:3306/test

        Oracle: jdbc:oracle:thin:@localhost:1521/test

        public static Connection getConnection(String url,String user,String password) throws SQLException

        public static Connection getConnection(String url,Properties info) throws SQLException

        public static Connection getConnection(String url) throws SQLException       

 

2、Connection

   所有的数据库操作都是基于链接之上的。

   Statement createStatement():创建向数据库发送sql的statement对象。即Statement stmt = conn.createStatement();//创建向数据库发送sql的statement对象

   preparedStatement(sql): 创建向数据库发送预编译sql的Prepare Statement对象。

   preparedCall(sql): 创建执行存储过程的Callable Statement对象

   setAutoCommit(boolean autoCommit):设置事务是否自动提交

   commit():在链接上提交事务

   rollback():在此链接上回滚事务

 

3、Statement

   作用:代表SQL语句对象。可以向数据库发送任何的SQL语句

   ResultSet executeQuery(String sql):执行sql查询,sql一般都是查询语句,返回ResultSet

   int executeUpdate(String sql):sql一般是DML(insert update delete)语句。返回int值,操作几条记录。

   boolean execute(String sql):sql可以是任意的语句。返回值不是代表成功与否。如果是查询语句,就有结果集,返回true。没有返回结果集的,返回false。

   addBatch(String sql):把多条sql语句放到一个批处理中。

   executeBatch():向数据库发送一批sql语句执行。

 

4、ResultSet

   作用:封装了查询的结果集。封装执行结果时,采用类似表格的方式。ResultSet对象维护了一个指向数据行的游标,默认指向表格第一行数据内容的前面。

   方法:X getX(String columnName或 int columnIndex) 其中X为String,int,long等类型

 

补充,游标的操作:

     boolean next():游标下移。返回值是有无记录

     boolean previous():游标上移。

     boolean absolute(int count):定位到指定的行。第一行是1。

     void beforeFirst():移动游标到第一行的前面。

     void afterLast():移动游标到最后一行的后面。

 

四、释放占用的资源

   一定要释放资源,所以写到finally里。

五、SQL注入

       SQL注入攻击指的是黑客通过构建特殊的命令作为参数传入Web程序,而这些命令大都是SQL语法里的一些基本组合。当条件为' or 1=1 and id ='可以当条件查询。

如:select * from user where name='' or 'a'='a';

       select * from user where name='' or 1=1

       等价于 select * from user

       SQL注入分为平台注入和代码层注入。前者是由不安全的数据库配置或数据库平台的漏洞导致;后者主要是由于程序员对输入未进行细致的过滤,从而执行了非法执行。

       产生原因:

①不当的类型处理

②不安全的数据库配置

③不合理的查询集处理

④不当的错误处理

⑤转义字符处理不合适

⑥多个提交处理不当

       SQL注入的预防:

    ①用户的表单输入域:防止一些特殊字符。

    ②对密码加密:MD5加密

    ③PreparedStatement预编译(得到该对象时,就必须给他SQL语句)

      支持参数占位符:  ?  一个问号代表着一个参数。

      注:能用PreparedStatement就不要用Statement。

 

六、如何调用存储过程

Mysql:

inputParam为输入参数,inOutParam既可以作为输出参数,又可以作为输入参数。

Oracle:

七、事务

1、事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

   MySQL:每一条语句都属于独立事务,默认自动管理的。

2、相关操作内容:

    开启事务:start transaction; //日后的语句都会处于同一个事务之中。

    提交事务:commit;

    回滚事务:rollback;

3、事务的特性(数据安全):

原子性:处于事务中的多条语句是不可分割的。(当做一个整体对待,操作事务要么都发生,要么都不发生)

一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如:转账,转账前A+B=2000,转账后A+B=2000

隔离性:多线程并发。一个事务不能被其他线程中的事务所打扰。

持久性:事务一旦提交,永久保存起来。(保存到硬盘,而不是内存)

4、事务的隔离级别:属于事务的。都已开启了事务为前提。

不考虑事务的隔离级别,会出现以下情况(是错的)

  1. 脏读:一个线程中的事务读到了另外一个线程中未提交的数据。
  2. 不可重复读:一个线程中的事务读到了另外一个线程中已经提交的update的数据。
  3. 虚读:一个线程中的事务读到了另外一个线程中已经提交的insert的数据。

 

要想避免以上现象,通过更改事务的隔离级别来避免:()

  1. READ UNCOMMITTED “脏读、不可重复读、虚读”都有可能发生。
  2. READ COMMITTED 避免脏读的发生,“不可重复读、虚读”有可能发生。
  3. REPEATABLE READ 避免“脏读、不可重复读”的发生,虚读有可能发生。
  4. SERIALIZABLE 避免“脏读、不可重复读、虚读”的发生。

 

级别依次升高,效率依次降低,数据越安全。

MySQL:默认REPEATABLE READ

ORACLE:默认READ COMMITTED

 

⑴MySQL:

select @@tx_isolation;//查看当前会话的隔离级别

set transaction isolation level 级别;// 设置当前的事务隔离级别

⑵Oracle:

1.查看系统默认事务隔离级别,也是当前会话隔离级别

--首先创建一个事务
declare
     trans_id Varchar2(100);
  begin
     trans_id := dbms_transaction.local_transaction_id( TRUE );
  end; 

--查看事务隔离级别

SELECT s.sid, s.serial#,

CASE BITAND(t.flag, POWER(2, 28))
WHEN 0 THEN 'READ COMMITTED'
ELSE 'SERIALIZABLE'
END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');

八、连接池

  1. 连接池:是创建和管理一个连接的缓冲池的技术。
  2. 编写连接池:

     用一个实现了javax.sql.DataSource类的实例时,用户如果调用Connection.close()方法,会把链接关闭,失去了连接池的意义,而我们需要实现完实例后,放回连接池里,方便下一次的使用,而不是立马关闭。所以使用包装设计模式,而包装设计模式的核心是保持被包装对象的原有信息,又可以对某个或某些方法进行改写

  ⑴流程如下,即用包装(装饰)设计模式:

   ①编写一个类,实现与被包装类(即数据库驱动对Connection的实现)相同的接口。(使这个类和数据库的驱动实现有着相同的行为)

   ②定义一个变量,引用被包装类的实例。

   ③定义构造方法,传入被包装类的实例。

   ④对于要改写的方法,编写自己的代码即可。

   ⑤对于不需要改写的方法,调用原有对象的对应方法。

 

 ⑵为何不用继承的方法来改写close()方法:

   ①因为数据库的种类比较多,要写继承的话会写死,因为他是继承相对应数据库的架包里的方法。

   ②数据库驱动对Connection接口的实现类,不允许被继承

   ③假设能继承成功了,丢失了原有对象的信息。

3.连接池的动态代理(Aspect-Oriented Programming,简称AOP,即默认适配器设计模式)

3.1动态代理技术介绍

3.1.1代理模式:

     就是为其他对象提供一种代理以控制对这个对象的访问。即明星与经纪人关系,经纪人即代理,联系代理,由代理转交给明星。

3.1.2基于接口的动态代理:Proxy;如果一个类没实现任何的接口,此种代理就不能使用了。

说明:Proxy创建动态代理类的实例提供了静态方法,也是所有动态代理类的父类的方法创建。是JDK自带的。

  InvocationHandler handler = new MyInvocationHandler(...);

  Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });

  Foo f = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).

                                   newInstance(new Object[] { handler });

或者更简单的:

  Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class },handler);      

             

3.2基于接口的连接池动态代理:Proxy

3.3基于子类的动态代理:CGLIB;子类可以扩展父类的功能

     前提:被代理类的要求

a、不能是final的

b、必须是public的

比如普通的JavaBean就可能没有实现任何的接口。

代理类是被代理类的子类。   

 

4.开源第三方数据源使用(DBCP、C3P0和JDNI)

4.1 JDNI(Java Naming and DIrectory Interface)

⑴拷贝数据库的驱动到Tomcat\lib目录下

⑵在web应用的META-INF目录下建立一个名称为context.xml的配置文件

⑶获取JNDI容器中的资源

Lookup里的地址后面需要跟第二步里面起的一致。

补充:JDNI的包放在javax.naming.*里,不要在main方法中获取数据源,获取不到。

 

4.2 DBCP(APache组织实现的。DBCP:DataBase Connection Pool)

需要架包:commons-dbcp-1.4.jar和commons-pool-1.5.6.jar

4.3 C3P0

需要架包:c3p0-0.9.1.2.jar

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值