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接口 : 自己封装 对象
浙公网安备 33010602011771号