JDBC

空格空格空格空格1.JDBC驱动 JDBC技术

                                                                       

 

空格空格空格空格2.JDBC常用类和接口

                             空格空格JDBC有关的类:都在 java.sql 和 javax.aql(扩展包) 包下。具体的类如下图所示:

                                                                                            

                                    空格空格DriverManger:数据库驱动管理类。作用:1)注册驱动;2)创建java和数据之间的连接,即获取Connection接口;

                                    空格空格Connection:是一个接口。作用:建立数据库和java代码之间的连接;

                                    空格空格Statement(接口),PreparaedStatement(接口,解决安全隐患问题,如sql注入问题),CallbackStatement(操作存储过程,oracle会讲解):向数据库发送sql语句,操作数据库;

                                    空格空格ResultSet(接口):结果集,Statement发送sql语句,得到的结果,封装在ResultSet中。


空格空格空格空格3.JDBC快速入门

                             空格空格1.确定启动mysql数据库;2.创建数据库和表(例:user表),并添加数据;3.新建项目,并在项目中新建lib文件夹,将mysql驱动jar包导入(复制粘贴)lib文件夹下;

                                    空格空格4.需求:快速遍历user表的所用信息,一共六步:

                                    空格空格空格空格1)注册数据库驱动:1)DriverManager.registerDrier(new Driver);空格空格2)new Driver;空格空格3)Class.forName("com.mysql.jdbc.Driver");空格空格4)从JDBC4.0开始,目前普遍使用的版本,不用注册驱动而直接使用。

                                    空格空格空格空格空格空格public static void registerDriver(Driver driver) throws SQLException空格空格注意:方法的参数是Driver,这是jdbc的一个接口,所以我们需要给定实现该接口的实现类;

                                                                                                                                                                                                                                      如果我们连接的是mysql数据库,那么需要导入mysql数据库提供的包,也就是com.mysql.jdbc.Driver; 下的Driver类;

 

                                                                                                                                                                                                                                      如果我们连接的是oracle数据库,那么需要导入oracle数据库提供的包。

                                                                                                                                                                                                                           注意:在实际开发中并不推荐采用registerDriver方法注册驱动。

 

 

                                    空格空格空格空格2)获取数据库连接Connection对象:1)Connection conn = DriverManager.getConnection(url, user, password);空格空格2)从连接池中获取;

                                                                                             

 

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

                                    空格空格空格空格空格空格String url = "jdbc:mysql://127.0.0.1:3306/数据库名";或  " jdbc:mysql://localhost:3306/数据库名" 是固定格式;简写形式:jdbc:mysql:///数据库名,不建议使用简写方式;

                                    空格空格空格空格空格空格属性:useUnicode=true&characterEncoding=utf8(很少使用),是否使用Unicode字符集,如果本参数值设置为true,表示是。                                                           

                                    空格空格空格空格空格空格解决问题:如果java代码操作数据库时发生中文乱码问题,按照如下格式解决:jdbc:mysql://localhost:3306/day04_db?useUnicode=true&characterEncoding=utf8。

                                    空格空格空格空格空格空格String user:数据库用户名;String password:数据库密码;

                                    空格空格空格空格3)创建发送sql的Statement对象:Statement st = conn.createStatement();

                                    空格空格空格空格或者创建发送sql的PreparedStatement对象  conn.preparedStatement(sql) 对SQL语句进行预编译,防止SQL注入;

                                    空格空格空格空格Statement 接口中的方法:executeQuery(sql);空格空格executeUpdate(sql);

                                   空格空格空格空格4)执行sql语句,并且获取返回结果:ResultSet rs = st.executeQuery(sql);

                                   空格空格空格空格5)遍历结果集原理:

                                                                                           

 

                                                                                                                                                                                                                                                              注意:根据数据库内部列类型,选择相应 getXXX方法来获取数据。

                                                                                                                                                                                                                                                                         while(rs.next()){     int ---- getInt()    varchar ---- getString()    date ----- getDate()    }

                                                                                                                                                                                                                                                              注意:每一次循环遍历我们获取的是表中的一行数据。

                                    空格空格空格空格空格空格int id = rs.getInt("id");空格空格id:数据库 表中 的列名;

                                    空格空格空格空格空格空格String username = rs.getString("username");空格空格username:数据库 表中 的列名;

                                    空格空格空格空格空格空格说明:获取具体的结果,使用ResultSet 类的对象调用  getXX方法来获取具体的列值。

                                    空格空格空格空格6)释放资源:

                                    空格空格空格空格 Jdbc中,数据库连接资源是非常珍贵的,数据库允许的并发访问连接数量有限。因此,当数据库资源使用完毕后,一定要记得释放资源。哪怕程序出现异常,也需要释放资源。对于这样一个情况,我们需要将资源释放的操作放在finally代码块                                                                         中。无论怎样,只要开辟了数据库资源,即使报了异常也要把数据库资源还给系统

 

空格空格空格空格4.JDBC CRUD操作(create(增加) read(查) update(更改) delete (删除))

 

空格空格空格空格5.JDBC工具类抽取

                                    空格空格0. JdbcUtil (封装思想)

                                    空格空格1. 获取连接 : 配置文件 保存 一些信息

                                    空格空格2. 释放资源

空格空格空格空格6.sql注入问题

                                    空格空格恶意注入方式一:elect * from user where username ='xxxxx' and password ='xxx' or '1'='1'

                                    空格空格空格空格对于上述sql语句进行说明:

                                    空格空格空格空格空格空格username ='xxxxx' and password ='xxx' 表示用户名和密码必须都得满足。

                                    空格空格空格空格空格空格username ='xxxxx' and password ='xxx' or '1'='1' :由于or后面是 '1'='1' 永远是true,所以无论用户名和密码是什么都会满足条件,即都会将数据库中的所有用户都查询出来。

                                    空格空格恶意注入方式二:select * from user where username ='zhangsan' -- ' and password ='kajajha' ;

                                    空格空格空格空格对于上述sql语句进行说明:

                                    空格空格空格空格空格空格-- ' and password ='kajajha''' ; -- 表示注释的意思,这样就会将密码都给注释掉了,就相当于只根据用户名zhangsan来查询了。

                                    空格空格问题根本原因:

                                    空格空格空格空格之所以有sql注入的问题,无非是在参数中设置了一些特殊字符,使sql语句在拼接这些参数的时候因为特殊字符的原因改变了sql语句原来的规则。

                                    空格空格问题的解决方案:

                                    空格空格空格空格PreparedStatement是Statement的子接口,可以防止sql注入问题。

                                    空格空格空格空格PreparedStatement 解决步骤:

                                    空格空格空格空格空格空格1)PreparedStatement  pstmt =  conn.prepareStatement(sql); -----需要你事先传递sql。如果sql需要参数,使用?进行占位。

                                    空格空格空格空格空格空格2)设置参数(执行sql之前):pstmt.setXXX(int index, 要放入的值) -----根据不同类型的数据进行方法的选择。第一个参数index表示的是?出现的位置。从1开始计数,有几个问号,就需要传递几个参数;第二个参数:给问号的位置                                                                                          传入的值。

                                    空格空格空格空格空格空格3)执行:pstmt.executeQuery();---执行select空格空格 pstmt.executeUpdate();---执行insert,delete,update

 

空格空格空格空格7.连接池原理

                                                                              

 

空格空格空格空格8.自定义连接池

                                    空格空格恶数据库连接池的实现步骤:

                                    空格空格空格空格1)创建自定义连接池类 实现 javax.sql.DataSource接口;这是sun公司规定。

                                    空格空格空格空格2)创建保存数据库连接的集合类使用LinkedList。 当做连接池。

                                    空格空格空格空格3)在自定义连接池类的构造函数中始化数据库连接池,批量创建与数据库的连接(Connection),把连接保存到集合中。

                                    空格空格空格空格4)实现DataSource这个接口中的getConnection()方法,每次调用getConnection方法时,从集合对象中取一个connection对象给用户。

                                    空格空格空格空格5)使用完connection 连接,调用自定义的backPool方法,将connection连接放回集合中,不要交给数据库。这里只是将连接放回到连接池中,而不是关闭连接。

 

空格空格空格空格9.装饰模式和动态代理实现close方法

                                    空格空格数据库连接池中的连接,用完了应该放回连接池,不能关闭。通过自定义了一个backPool方法实现的放回,废弃Connection接口的close方法。如果能将close方法从原来的释放连接  改成  将连接还给连接池,就解决这个问题了!

                                    空格空格空格空格1)装饰Connection模式:略

                                    空格空格空格空格2)动态代理:

 1 /*
 2      * 动态代理:在不改变原有类的基础上,改写类的一些方法。这是一种格式。
 3      * */
 4     @Override
 5     public Connection getConnection() throws SQLException {
 6         //从池子中获取连接
 7         System.out.println("从池子中获取连接");
 8         final Connection con = pools.removeLast();    
 9         /*
10          * 第一个参数:被代理对象的类加载器。
11          * 第二个参数:被代理对象的实现的接口。
12          * 第三个参数:代理类需要做的工作。
13          * */
14         Connection proxyCon = (Connection)Proxy.newProxyInstance(con.getClass().getClassLoader(),new Class[]{com.mysql.jdbc.Connection.class}, new InvocationHandler() {
15             
16             /*
17              * 第一个参数:代理对象本身
18              * 第二个参数:被代理类的方法
19              * 第三个参数:arg1方法执行所需要的参数
20              * */        
21             @Override
22             public Object invoke(Object arg0, Method arg1, Object[] arg2)
23                     throws Throwable {
24                 if("close".equals(arg1.getName())){
25                     System.out.println("改写close方法");
26                     //只改写close方法
27                     //将con放到连接池就行了。
28                     pools.add(con);
29                     System.out.println("此时池子 中还有"+pools.size()+"个连接");
30                     return null;
31                 }else{
32                     //保持原有方法的功能
33                     return arg1.invoke(con, arg2);
34                 }    
35             }
36         });
37         return proxyCon;
38     }

 

 

  空格空格空格空格10.常用开源连接池

                                       空格空格DataSource本身只是Sun公司提供的一个接口,没有具体的实现,它的实现由连接池的数据库厂商去实现。我们只需要学习这个工具如何使用即可。常用的连接池实现组件有这些:

                                       空格空格空格空格l  C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0有自动回收空闲连接功能

                                       空格空格空格空格l  阿里巴巴-德鲁伊druid连接池:Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和SQL解析器组成。该项目主要是为了扩展JDBC的一些限制,可以让程序员实现一些特殊的需求。

                                       空格空格空格空格l  DBCP(DataBase Connection Pool)数据库连接池,是Apache上的一个Java连接池项目。dbcp没有自动回收空闲连接的功能。

                                       空格空格1)C3P0连接池:空格空格A.导jar包到项目lib文件夹;空格空格B.配置c3p0-config.xml到项目src文件夹;空格空格C.ComboPooledDataSource cpds = new ComboPooledDataSource();

                                       空格空格空格空格如何快速切换不同的数据源呢? 根据实例化数据源ComboPooledDataSource(String configName) 指定不同的参数;

                                       空格空格空格空格注意:

                                       空格空格空格空格空格空格1、配置文件名称是 c3p0-config.xml 文件,并且必须在src 目录下;

                                       空格空格空格空格空格空格2、c3p0会自动寻找这个文件,加载里面的配置信息。

 

                                       空格空格空格空格c3p0-config.xml模板:

 

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
  <default-config>
        <!--  1. 数据库的连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/day05</property>
    <property name="user">root</property>
    <property name="password">123</property>
    
    <!-- 2. 连接池参数 -->
      <!--初始连接数-->
    <property name="initialPoolSize">5</property>
      <!--最大连接数-->
    <property name="maxPoolSize">10</property>
    <!--等待多久以后抛出异常-->
    <property name="checkoutTimeout">2000</property>
  </default-config>

  <named-config name="day04">
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/day_04db</property>
    <property name="user">root</property>
    <property name="password">123</property> 
  </named-config>
</c3p0-config>

 

 

 

                                       空格空格2)DRUID(阿里巴巴-德鲁伊)连接池:空格空格A.导jar包到项目lib文件夹;空格空格B.配置druid.properties到项目文件夹;空格空格C.核心类:DruidDataSourceFactory中静态方法public static DataSource createDataSource(Properties properties):读取属性配置文件,创建一个数据源对象。

                                       空格空格空格空格druid.properties模板:

# 数据库连接参数
url=jdbc:mysql://localhost:3306/day05
username=root
password=123
driverClassName=com.mysql.jdbc.Driver
# 连接池的参数
initialSize=3
maxActive=10
maxWait=2000

 

 

   空格空格空格空格11.JDBCTemplate

 

    0. 核心API: JdbcTemplate
    1. DDL操作 : execute (了解)

    2. DML操作 : update (重要)

    3. DQL操作 : query
        1. 不同情况
            1. 单行单列的情况(结果只有一个值)

            2. 单行多列的情况

            3. 多行多列的情况

        2. API
             1. queryForObject 单行单列 (重要)

            2.  queryForMap   单行多列
        
             3. queryForList  多行多列
         
             4.  query (重要)
                 1.  BeanPropertyRowMapper 实现类  和  javabean的定义
                     1.  自动封装对象,大大简化代码
                     2.  底层原理: 反射
                 2.  RowMapper接口 : 自己封装 对象

 

posted @ 2018-08-23 18:39  z2018w  阅读(86)  评论(0)    收藏  举报