JDBC
1 JAVA DATABASE CONNECTION
导入jar包:驱动
加载驱动类:Class.forName("类名");
给出url username password 其中url背下来 jdbc:
使用DriverManger来得到Connection
jdbc四大配置参数:
driverClassName:com.mysql.jdbc.Driver
url:jdbc:mysql://localhost:3306/数据库名
username:账户名
password:密码
jdbc协议:jdbc:厂商名称:子协议(由厂商自己规定)
mysql子协议://主机:端口号/数据库名称
2原理 Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb1";String username = "root";String password = "123";Connection con = DriverManager.getConnection(url,username,password);String url = "jdbc:mysql://localhost:3306/数据库名";String username = "root";String password = "123";Connection con = DriverManager.getConnection(url,username,password);
所有的java.sql.Driver实现类,都提供了static块,块内的代码就是把自己注册到DriverManger中
jdbc4.0之后,每个驱动jar包中,在META-INF/service目录下提供了一个名为java.sql.Driver的文件
内容就是该接口的实现类名称
3 完成增删改查
1 通过Connection对象创建Statement 方法createStatement()
2 调用方法int executeUpdate(String sql) 它可以发送DML DDL 返回影响的行数 (sql语句不用加分号)
3 调用方法ResultSet executeQuery(String sql),可以发送DQL 之后再对返回的表格进行解析
` ResultSet:
把行光标移动到下一行,可以调用next()方法完成 方法返回的是boolean
通过列编号或者列名获取值 getxxx()方法
4 关闭资源
倒关:先开的后关,后开的先关
4 jdbc代码规范化
1 在try外给出引用的定义
2 在try内对象实例化
3 在finally中进行关闭
5 Connection
获取Statement
Statement stmt = con.createStatement() 这个方法可以带两个参数来确定创建的Statement能生成什么样的结果集
6 Statemnet
方法:
int executeUpdate(String sql)
ResultSet executeQuery(String sql)
boolean execute() 可以执行所有的SQL语句,返回值表示是否有结果集
7 ResultSet之滚动结果集(了解)
表示结果集,是一个二维表格,ResultSet内部维护一个行光标(游标),ResultSet提供一系列方法来移动游标
获取结果集元数据
得到元数据:rs.getMetaData() ,返回值为ResultSetMetaData;
获取结果集列数:int getColumnCount()
获取指定列的列名:String getColumnName(int a)
8 结果集特性
createStatement() 已确定了Statement生成的结果集是什么特性
第一个参数:
ResultSet.TYPE_FORWARD_ONLY:不滚动结果集
ResultSet.TYPE_SROLL_INSENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化
ResultSet.TYPE_SCROLL_SENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化(一般数据库不支持)
第二个参数:
CONCUR_RED_ONLY:结果集是只读的,不能通过修改结果集而反向影响数据库
CONCUR_UPDATABLE:结果集是可更新的,对结果集的更新可以反向影响数据库
是否可滚动:
是否敏感:
是否可更新:
9 PreparedStatement
Statement的字接口
1 防SQL攻击
2 提高代码的可读性,可维护性
3 提高效率
得到:
sql模板:所有的参数使用?来替代
调用Connection的PreparedStatement prepareStatement(String sql模板)
调用方法setString(int a,String b)方法为参数赋值 第一个参数为第几个问号,第二个参数为值
调用方法executeUpdate() 方法 或者 executeQuery() 方法不需要参数
预处理的原理:
1 服务器的工作:
校验sql语句的语法
编译:一个与函数相似的东西
执行:调用函数
2 PreparedStatement :
前提:连接的数据库必须支持预处理,几乎没有不支持的
每个对象都与sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译。执行时
只是把参数传递过去而已,第二次执行时,就不用再次检验语法,直接执行就可以
预处理功能默认是关闭的。须使用参数打开 url后加?useServerPrepStmts=true&cachePreStmts=true
10 DAO模式
DAO 模式就是写一个类,把访问数据库的代码封装起来。DAO在数据库与业务逻辑之间
DAO模式需要先提供一个DAO接口
然后再提供一个DAO接口的实现类
再编写一个DAO工厂,Service通过工厂来获取DAO实现
11 时间类型
数据库类型与java中类型的对应关系
DATE->java.sql.Date
TIME->java.sql.Time
TIMESTAMP->java.sql.Timestamp
时间类型的转换
java.util.Date->java.sql.Date、Time、Timestamp
把util的Date转换成毫秒值
使用毫秒值创建sql的Date,TIME,Timestamp
java.sql.Date、Time、Timestamp->java.util.Date 这一步无需处理 ,都是java.util.Date的子类
12 大的字节数据,字符数据
存入时
需要得到Blob
1 我们有的是文件,目标是Blob
2 先把文件变成byte[]
3 在使用byte[] 创建Blob blob = new SerialBlob(byte[] byte) 之后再 setBlob(xx,blob)
在my.ini添加如下配置(在文件末尾)
max_allowed_packet=10485760
取出时:
1 通过Blob得到输入流对象 getBinaryStream()
2 自己创建输出流对象
3 把输入流的数据写到输出流中
12 PrepareStement 批处理
只针对更新(增 删 改)语句
对象内部有集合
1 用循环向该对象添加sql参数 循环句的末尾addBatch()
2 调用它的执行方法 executeBatch()
需要打开批处理的功能:url后加?rewriteBatchedStatements=true
13 事务的四大特性(ACID)
原子性
一致性
隔离性
持久性
15 mysql中的事务
开启事务:start transaction
结束事务:commit或rolback(回滚)
16 JDBC事务
在jdbc中处理事务,都是通过Connection完成的
同一事务中所有的操作,都在使用同一个Connection对象
setAutoCommit(boolean):设置是否自动提交事务,如果为true(默认)表示自动提交,也就是每条执行的sql语句都是一个单独的事务,如果设置为false。
那么相当于开启事务 con.setAutoCommit(false)表示开启事务
commit() 提交结束事务
rollback() 回滚结束事务
try{
con.setAutoCommit(false);
.......
con.commit();
}catch(){
con.rollback();
}
17 事务的隔离级别
1 事务的并发读问题
脏读:读取到另一个事务未提交数据
不可重复读:两次读取不一致
幻读;读到另一事务已提交数据
2 四大隔离级别
1 SERIALIZABLE(串行化) 处理了任何问题 性能差
2 REPEATABLE READ(可重复读) 防止脏读和不可重复读 mysql默认
3 READ COMMITTED(读已提交数据) 防止脏读 oracle默认
4 READ UNCOMMITTED(读未提交数据) 可能出现任何问题
18 数据库连接池
连接池也是使用四大连接参数来完成创建的
连接池必须实现:javax.sql.DataSource接口
连接池返回的Connection对象,close()方法不是关闭,而是归还给池
连接池使用mysql对象进行了装饰,只对close方法进行了增强
dbup连接池:
1 创建连接池对象 BasicDataSource dataSource = new BasicDataSource()
2 配置四大参数 setxxx() 方法 DriverClassName Url Usename Password
3 配置池参数 setMaxActive(int )最大连接数 setMinIdle(int )最小空闲连接 setMaxWait(int ) 最大等待时间
4 得到连接对象 getConnection()
19 C3P0连接池
底层使用动态代理
ComboPooleDataSource
方法getConnection()
DataSource 表示连接池对象
配置四大参数
setDriverClass()
setJdbcUrl()
setUser()
setPassword()
池有默认值,可以不配置,也有相关的配置方法
可指定配置文件
要求:
文件名称:必须在c3p0-config.xml
文件位置:必须在src下
<c3p0-config>
<default-config>
<property name="配置名称">配置信息</property >
........
</default-config>
这里还可有为oracle提供的配置信息
</c3p0-config>
20 Tomcat配置连接池
JNDI 在服务器配置资源,然后通过统一的方式来获取配置的资源
<Context>
<!--
name:指定资源的名称
factory:资源由谁来创建
type:资源的类型
其他的东西都是资源的参数
-->
<Resource name="jdbc/dataSource"
factory="org.apache.naming.factory.BeanFactory"
type="com.mchange.v2.c3p0.ComboPooldeDataSource"
driverClass=""
jdbcUrl=""
user=""
password=""
/>
</Context>
获取资源
1 创建JNDI的上下文对象
Context cxt = new InitialContext();
2 查询入口
Context envContext = (Context)cxt.lookkup("java:comp/env");
3 进行二次查询
使用的是名称与<Resource>元素对应的name
DataSource dataSource = (DataSource)envContext.lookup("jdbc/dataSource");
Connection con = dataSource.getConnection();
或者 DataSource dataSource = (DataSource)cxt.lookup("java:comp/env/jdbc/dataSource");
21 ThreadLocal<T> 内部是一个Map Map<Thread,T> Map的键值为当前线程
方法 set(Object) get(Object) remove(Object)
22 dbUtils
QueryRunner(DataSource a) 类
方法
int update(sql模板,Object.....)增删改
int update(Connection con,String sql ,Object... params) 需要调用者提供Connection ,支持事务
T query(sql模板,ResultSetHander的实现类,Object.....) 查 会返回指定类型的javabean对象
T qurey(Connection con,String sql,ResultSetHandler rsh,Object... params)
ResultSetHander的实现类(结果集处理器) 内部调用handle() 方法转换成需要的类型
new BeanHandler<T>(T.class); 要求列名与属性一样
BeanHandler(单行) 构造器需要一个Class类型的参数,用来把一行结果转换成指定类型的javabean对象
BeanLisHandler(多行) 构造器也是需要一个Class类型的参数,用来把一行的结果集转换成一个javabean,那么多行就是转换成List对象,一堆javabean
MapHandler(单行) 把一行结果集转换成Map对象
MapListHandler(多行) 把一行记录转换成一个Map,多行就是多个Map,即List<Map>
ScalarHandler(单行单列) 通常与Select count(*) from t_stu语句!结果集是单行单列的,它返回一个Object
23 BaseServlet
1 我们希望在Servlet中可以有多个请求处理方法
2 要求用户发出请求时,必须给出一个参数,来说明要调用哪一个方法
请求处理方法的签名必须与service相同,即返回值和参数,以及声明的异常都相同
23 分页
Servlet
当前页面:
总页数:总记录数/每页记录数
总记录数:totalRecored
每页记录数:业务数据或叫系统数据
当前页数据
url
数据的传递:
这些分页数据总要在各层之间来回的传递
我们把这些分页数据封装到一个javabean中
分页在各层中的处理
页面:给出分页相关的链接
页面需要给Servlet传递什么;有可能传递页码
Servlet: 创建PageBean 对象,给PageBean所有的属性赋值,然后传递给页面
Servlet需要给Dao传递页码,每页记录数
Service : 略
Dao:
tr:select * from ...
beanList : select # from t_custom limit x,y
1 得到pc和ps,创建出PageBean
2 要查询数据库得到tr和备案list
3 返回PageBaen
显示分页页码表
· 最多显示页码表
当前页,在页码表中的位置,定为6
只需要当前页码就可以定出来页码列表
定下页码列表只需两样数据
begin
end
需要使用pc来推算吃begin和end
计算公式:
如果总页数<=10(列表长度),那么begin=1,end=总页数
使用公式计算:begin=pc-5,end = pc+4
头溢出:当begin<1时,让begin=1
尾溢出:当end>${tp}时,让end=${tp}
在超链接中要保留参数
当使用多条件查询后,在点击第2页时,这个第2页超链接没有条件了,所以会丢失条件
所以我们需要在所有页面上的链接都要保留条件
我们要把条件以一个字符串的形式保存到PageBean的url中,由servlet完成