JDBC学习笔记

来源:互联网 发布:淘宝男装t恤花色 编辑:程序博客网 时间:2024/06/06 18:12
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
--------------------------------------------------------------------------------------------------------
day01
--------------------------------------------------------------------------------------------------------
开发前配置准备工作:
1>下载.m2和apache-maven-3.9.9-bin文件;
2>将.m2解压放到C:\Users\Administrator 文件夹下面(.m2必须放在C:\Users\Administrator );
3>将apache-maven-3.9.9-bin解压放在任意没有中文名字磁盘路径下;
4>打开Window-->preference-->Maven-->User Settings;
5>将Global Settings设置为:apache-maven-3.3.9-bin\apache-maven-3.3.9\conf\settings.xml;
6>将User Settings设置为:apache-maven-3.3.9-bin\apache-maven-3.3.9\conf\settings.xml;
7>点击Apply更改设置;
8>打开Window-->Show View-->Other-->Maven Repositories;
9>Maven Repositories窗口中:Local Repositories-->右键Loacal Repository-->Rebuild Index;
10>New->Other-->搜索Maven->Maven Project-->Create a simple project打钩-->next;
11>Group id表示包名,Aftifact id表示项目名。
JDBC标准:
1>Java Database Connectivity:Java访问数据库的解决方案。
2>希望用相同的方式访问不同的数据库,以实现与具体数据库无关的Java操作界面。
3>JDBC定义一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库的特点去实现这些接口。
4>驱动管理:DriverManager。
5>连接接口:Connection、DatabaseMetaData。
6>语句对象接口:Statement、PreparedStatement、CallableStatement。
7>结果集接口:ResultSet、ResultSetMetaData。
8>JDBC工作过程:
- 加载驱动,建立连接;
- 创建语句对象;
- 执行SQL语句;
- 处理结果集;
- 关闭连接。
9>驱动类加载方式(Oracle):Class.forName("oracle.jdbc.driver.OracleDriver");
10>封装驱动类,驱动类通过static块实现在DriverManager中的“自动注册”。
11>ResultSet接口:执行查询SQL语句后返回的结果集,由ResultSet接口接收。
- 查询的结果存放在ResultSet对象的一系列行中;
- ResultSet对象的最初位置在行首;
- ResultSet.next()方法用来在行间移动;
- ResultSet.getXXX()方法用来获得字段的内容。
数据库厂商实现:
1>ORacle实现:
- 下载对应数据库驱动:ojdbc6.jar/ojdbc14.jar;
- 将驱动加载到项目中:MyEclipse:Build Path;
- 加载驱动类:Class.forName("oracle.jdbc.OracleDriver");
2>MySQL实现:
- 下载对应数据库驱动:mysql-connector-java-5.0.4-bin.jar;
- 将驱动加载到项目中:MyEclipse:Build Path;
- 加载驱动类:Class.forName("com.mysql.jdbc.Driver");
连接管理:
1>在工程中编写一个访问数据库的工具类,此后所有访问数据库的操作,都是从工具类中获取连接。
2>直接把数据配置写在工具类中(不建议此方法)。
3>把数据库配置写在一个properties属性文件里,工具类读取属性文件,逐行读取数据库参数。
4>在properties文件中,"#"符号表示注释。
5>在数据库中定义公共的关闭连接的方法,所有访问数据库的应用,共享此方法。
连接池技术:
1>为什么要使用连接池:
- 数据库连接的建立及关闭资源消耗巨大;
- 传统数据库访问方式: 一次数据库访问对应一个物理连接,每次操作数据库都熬打开、关闭该物
理连接,系统性能严重受损;
2>解决方案:数据库连接池(Connection Pool),系统初始运行时,主动建立足够的连接,组成一个池。每次应用程序请求数据库连接时,无需重新打开连接,而是从池中取出已有的连接,使用完后,不再关闭,而是归还。
3>连接池也只是接口,具体实现由厂商来完成。
4>使用Apache DBCP连接池:
- DBCP(DataBase Connection Pool):数据库连接池;
- Apache是一个Java连接池开源项目,同时也是Tomcat使用的连接池组件;
- 连接池是创建和管理连接的缓冲池技术,将连接准备好被任何需要他们的应用使用。
5>使用Apache DBCP需要的jar包:
- commons-dbcp-1.4.jar:连接池的实现;
- commons-pool-1.5.jar:连接池实现的依赖库。
6>通过DataSource获取连接。
7>连接池常用参数有:
- 初始连接数;
- 最大连接数;
- 最小连接数;
- 每次增加的连接数;
- 超时连接;
- 最大空闲连接;
- 最小空闲连接。
异常处理:
1>java.sql.SQLException是在处理JDBC时常见的exception对象。
2>SQLException用来表示JDBC操作过程中发生的具体错误。
3>常见异常:登录被拒绝、列明无效、无效字符、无法转换为内部表示等。
4>SQLException属于Checked Exception,必须使用try...catch或者throw明确处理。
--------------------------------------------------------------------------------------------------------
day02
--------------------------------------------------------------------------------------------------------
Statement执行查询:
1>创建Statement的方式:Statement statement = Connection.createStatement();
2>执行INSERT,UPDATE和DELETE:Statement.executeUpdate();返回执行后影响的记录数。
3>执行SELECT:Statement.executeQuery();
4>执行查询:Statement rs = statement.executeQuery(sql);方法返回SQL语句执行后的结果集。
PreparedStatement语句:
1>Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句。
2>Statement每执行一次都要对传入的SQL语句编译一次,效率较差。
3>某些情况下SQL语句只是其中的参数有所不同,其余子句完全相同,适用于PreparedStatement。
4>预防sql注入攻击。
5>PreparedStatement是接口,继承自Statement。
6>SQL语句提前编译,三种常用方法execute、executeQuery、executeUpdate已被更改,不再需要参数。
7>PreparedStatement实例包含已事先编译的SQL语句。
8>SQL语句可有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。该语句为每个IN参数保留一个问号("?")作为占位符。每个问号的值必须在该语句执行之前,通过适当的SetInt或者SetString方法提供。
9>由于PreparedStatement对象已预编译过,所以其执行速度要快于Statement对象。因此,多次执行的SQL语句经常被创建为PreparedStatement对象,提高效率。
10>PreparedStatement是批处理的。
11>数据库具备缓存能力,可以对Statement的执行计划进行缓存,以免重复分析。
12>使用Statement本身作为key并将执行计划存入与Statement对应的缓存中。
13>对曾经执行过的Statements,再运行时执行计划将重用,降低开销。
14>SQL Injection简介:
- 场景:
String sql =
"select * from t where username = '" + name + "'and password = '" + passswd + "'";
- 输入参数后,数据库接收到的完整sql语句将是:
select * from t where username = 'scott' and password = 'tiger';
15>如果用户输入的passwd参数是:a' or 'b' = 'b,则数据库收到的SQL语句的where条件恒为true,这种现象被称为SQL注入。
16>对JDBC而言,SQL注入攻击只对Statement有效,对PreparedStatement无效,因为PreparedStatement不允许在插入参数时改变SQL语句的逻辑结构。
17>使用预编译的语句对象,用户传入的任何数据不会和原SQL语句发生匹配关系,无需对输入的数据做过滤。
18>JDBC支持三个日期类型(都继承自java.sql.Date):
- java.sql.Date:年月日
- java.sql.Time:时分秒
- java.sql.Timestamp:年月日时分秒
ResultSet结果集:
1>结果集遍历:
String sql = "select empno,ename,sal,hiredate from emp";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
double sal = rs.getDouble("sal");
Date hiredate = rs.getDate("hiredate");
}
rs.close();
2>ResultSetMetaData:数据结果集的元数据。
3>和查询出来的结果集相关,从结果集(ResultSet)中获取:
ResultSetMetaData rsm = rs.getMetaData();
int columnCount = rsm.getColumnCount();
String columnName = null;
for(int i = 1; i <= columnCount; i++) {
columnName = rsm.getColumnName(i);
}
4>常用的时ResultSet,初始指针在第一行之前(Before First)。
5>只能使用next()方法将指针向后移动,不能反向。一次移动一行,不能跳跃。
6>可滚动结果集:指针可以在结果集中任意移动。
7>可滚动结果集:
- Statement stmt = conn.createStatement(type,concurrency);
PreparedStatement stmt = conn.prepareStatement(sql,type,concurrency);
- type取值:TYPE_FORWARD_ONLY:只能向前移动,默认参数;
TYPE_SCROLL_INSENSITIVE:可滚动,不感知数据变化;
TYPE_SCROLL_SENSITIVE:可滚动,感知数据变化。
- concurrency取值:CONCUR_READ_ONLY:只读;
CONCUR_UPDATABLE:可更新。
8>元(Meta):本来、根本、本质。
9>元数据(MetaData):数据本质,数据的基本信息,用来描述某数据的数据。
10>结果集元素:用来描述结果集的数据,结果集的基本信息,多少列/列名/类型。
--------------------------------------------------------------------------------------------------------
day03
--------------------------------------------------------------------------------------------------------
事务处理:
1>事务简介:
- 事务(Transaction):数据库中保证交易可靠的机制,JDBC支持数据库中的事务概念;
- 在JDBC中,事务默认是自动提交的。
2>事务特性ACID:
- 原子性(Atomicity):事务必须是原子工作单位,对其数据修改,要么全部执行要么全都不执行;
- 一致性(Consistency):事务在完成时,必须使所有的数据都保持一致状态;
- 隔离性(Isolation):由并发事务所作的修改必须与任何其它并发事务所作的修改隔离;
- 持久性(Durability):事务完成之后,它对与系统的影响使永久的。
3>事务是数据库概念,JDBC支持事务,本质还是在数据库中实现的。
4>JDBC事务API:
- Connection.getAutoCommit():获得当前事务得提交方式,默认是true;
- Connection.setAutoCommit():设置事务的提交属性,参数是:
true自动提交,false不自动提交;
- Connection.commit():提交事务;
- Connection.rollback():回滚事务。
5>JDBC标准事务编程模式:
try {
//获得自动提交状态
autoCommit = con.getAutoCommit();
//关闭自动连接
con.setAutoCommit(false);
//执行SQL语句
stmt.executeUpdate(sql);
//提交
con.commit();
//将自动提交功能恢复到原来得状态
con.setAutoCommit(autoCommit);
//其他语句
} catch(SQLExeption e) {
//异常时回滚
con.rollback();
}
批量更新:
1>批量更新优势:
- 批处理:发送到数据库作为一个单元执行的一组更新语句;
- 批处理降低了应用程序和数据库之间的网络调用;
- 相比单个SQL语句的处理,批处理更为有效。
2>批量更新API:
- addBatch(String sql):Statement类的方法,可以将多条sql语句添加Statement对象的SQL语句列表中;
- addBatch():PreparedStatement类的方法,可以将多条编译的sql语句添加到PreparedStatement对象的SQL语句列表中;
- executeBatch():把Statement对象或PreparedStatement对象语句列表中的所有SQL语句发送给数据库进行编译;
- clearBatch():清空当前SQL语句列表。
3>防止OutOfMemory:
- 如果PreparedSatement对象中的SQL列表包含过多的待处理SQL语句,可能会产生OutOfMemory错误;
- 及时处理SQL语句:
for(int i=0;i<800;i++) {
sql = "insert into emp (empno,ename)
values(emp_seq.nextval,'name' + i + "'")";
//将SQL语句加入到Batch中
stmt.addBatch(sql);
if(i%500==0){
//及时处理
stmt.executeBatch();
//清空列表
stmt.clearBatch();
}
}
//最后一次列表不足500条,处理
stmt.executeBatch();
返回自动主键:
1>主表/从表关联关系,插入数据时需要保证数据完整性。
2>通过序列产生主键(Orcale):
- 在oracle中,建议主键通过序列获得:
String sql = "insert into (deptno,dname,loc) values(dept_seq.nextval,?,?)";
- 如果单表操作,不需要返回刚刚插入的主键值;
- 如果关联操作,需要将刚刚插入的主键值返回。
3>JBDC返回自动主键API:
- 方法一:先通过序列nextval获取序列的下一个值,再作为参数插入到主表和从表;
- 方法二:利用PreparedStatement的getGenerateKeys方法获取自增类型的数据,性能良好,只要一次SQL交互。
分页查询:
1>利用Oracle的rownum,传入SQL语句,以获得分页结果集。
2>计算分页结果集的起点和重点,替代SQL中的占位符:
- int begin = (page - 1)*pageSize + 1;
- int end = begin + pageSize - 1;
3>每次只向数据库请求一页的数据量。
4>内存压力小适合大数据量数据表。
5>另一种分页策略介绍:基于缓存的分页技术(加分页):
- 一次性把数据全部取出来放在缓存中,根据用户要看的页数(page)和每页记录数(pageSize),计算把哪些数据输出显示,将可滚动结果集的指针移动到指定位置;
- 只访问数据库一次,第一次取数据比较慢,以后每页都从缓存中取比较快;
- 比较合适小数据量,如果数据量大,对内存压力较大。
6>JDBC实现MySql分页查询:
- MySql实现方式:select * from t limit begin,pageSize;
- 在Java程序中,MySql和Oracle分页的方式,仅限于SQL语句不同。
DAO介绍:
1>DAO(Data Access Object):数据访问对象。
2>建立在数据库和业务层之间,封装所有对数据库的访问。
3>目的:数据访问逻辑和业务逻辑分开。
4>为了建立一个健壮的Java应用,需将所有对数据源的访问操作抽象封装在一个公共API中,包括:
- 建立一个接口,接口中定义了应用程序中将会用到的所有事务方法;
- 建立接口实现类,实现接口对应的所有方法,和数据库直接交互。
5>在应用程序中,当需要和数据源交互时则使用DAO接口,不涉及任何数据库的具体操作。
7>DAO通常包括:
- 一个DAO工厂类;
- 一个DAO接口;
- 一个实现DAO接口的具体类;
- 数据传递对象(实体对象或值对象)。
--------------------------------------------------------------------------------------------------------
0 0
原创粉丝点击