黑马小日子--JDBC
2012-08-05 14:48
267 查看
JDBC
一. JDBC简介:要操作不同的数据库,需要使用不同数据库的驱动,这对开发人员来说是一场灾难,所有万能的sun公司就定义了一套操作数据库的规范 :JDBC. 由具体的数据库厂商提供具体实现(数据库驱动).
JDBC简称: java database connectivity(java数据库连接),主要有接口组成
组成JDBC的有两个包:
Java.sql
Javax.sql
二.第一个JDBC案例:
实现目标: 使用JDBC操作数据库,并把数据答应到控制台上
编码步骤: 1. 加载驱动程序 DriverManager DriverManager.registerDriver(drivr); 2. 建立于数据库的连接(所有与数据库的操作都必须在连接的基础上进行)Connection Connection conn = DriverManager . getConnection(String url, String user, String password); 3. \建立发送sql语句的对象,并执行sql语句Statement Statement stmt = conn.createStatement(); 4. 如果存在查询结果,就返回封装了结果的对象.ResultSet ResultSet rs = Stmt . executeQuery(sql); 5. 打印出数据 While(rs.next()){ Syso(rs.getObject(字段名)) //有多少个字段,就写几个 } 6. 关闭占用的资源(按照开启顺序的反方向关闭资源) Rs.close(); Stmt . Close(); Conn. Close(); |
JDBC 规范中的主要接口: 1.DriverManager: 作用:注册驱动;建立数据库连接; 不推荐使用DriverManager方式来建立驱动 原因: 1.这种方式会造成驱动注册两次因为源代码中用静态代码库初始化了一个驱动,如果用DriverManager,就会再次注册一个驱动, 2.严重依赖数据库驱动.如果关掉驱动,数据库就挂了. 推荐使用:Class.forName("com.mysql.jdbc.Driver") 来注册驱动 常用数据库连接URL: Jdbc:mysql://localhost:3306/dbname MySql Jdbc:oracle:thin.@localhost:1521:sid 2.Connetcion 作用: 代表与数据库的连接 3.Statement(被PreparedStatement代替) 作用: 代表sql语句,能向数据库发送sql语句 常用方法: executeQuery(String sql); 执行查询语句,参数必须是select语句,返回结果集 executeUpdate(String sql); 执行添加,修改,删除记录的语句,参数必须是insert, update, delete语句,返回影响到的行数(int类型) Excute (String sql); 可以执行任何sql语句 返回boolean类型 如果sql是一个查询语句,,则有返回结果,即返回true,没有就放回 false 4.ResultSet 作用: 代表查询结果,有一个指针,默认指向第1条记录的前面(表头) 5.PreparedStatement 作用: 防止sql注入 提前预编译,提高效率 可以在sql中的参数使用占位符 使用这个代替Statement 6.释放资源. if(rs!=null){ Try{ Rs.close();; }catch(Exception e){ } Rs=null; //有助于垃圾回收器回收 } |
大数据也成为LOB(Large Objects),LOB又分为clob和blob,
Clob: 用于存储大文本
Blob: 用于存储二进制,例如声音,图片等
在MySql中,没有clob,只有blob,mysql中要存储大文本文件,使用的是text.
使用JDBC进行大文本处理
对于MySQL中的Text类型,可调用如下方法设置: 对MySQL中的Text类型,可调用如下方法获取: |
为什么要数据批处理?
因为当要处理很多很多条数据的时候,不适用批处理,就只能一条一条处理,这样的速度非常慢,所有要使用数据批处理.
数据批处理的两种方式:
一. PrepareStatement处理: 适合批处理sql语句相同,参数不同的语句
Connection conn=null; PreparedStatement ps=null; Try{ Conn=JdbcUtil.getConnection(); String str = " insert into batchdemo value(?,?)"; Ps=conn.prepareStatement(sql); For(int i=1;i< 100000000; i++ ){ //插入100000000条数据 ps.setInt(1,i); ps.setString(2,"aaa"+i); If(i%1000==0){ //如果缓存了1000条,就插入数据 ps.executeBatch(); //插入数据 ps.clearBatch(); //清空 } } ps.executeBatch(); //执行批量处理 }catch(){} |
Connection conn=null; Statement st=null; Try{ Conn=JdbcUtil.getConnection(); String sql1 = "insert into user(name, password) values ("qc","123")"; String sql2 = "insert into user(name, password) values ("dahai", "456")" St = conn . createStatement(); st.addBatch(sql1); //把sql1语句加入批处理命令 st.addBatch(sql2); //把sql2语句加入批处理命令 St. executeBatch(); }catch(){} |
Connection conn = JdbcUtil.getConnection(); String sql = "insert into user(name,password,email,birthday) values('abc','123','abc@sina.com','1978-08-08')"; PreparedStatement st = conn. prepareStatement(sql,Statement.RETURN_GENERATED_KEYS ); st.executeUpdate(); ResultSet rs = st.getGeneratedKeys(); //得到插入行的主键 if(rs.next()) System.out.println(rs.getObject(1)); 注:此参数仅对insert操作有效。 |
事务的概念:
事务的特性(ACID):
原子性(Atomicity):
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency):
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
隔离性(Isolation):
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
不考虑隔离性会出现的问题:
1.脏读: 一个事务独到另一个事务 未提交的 数据
2.不可重复读: 一个事物中,两次查询到的同一条记录的某些数据不同
3.虚读(幻读): 同一张表中,两次独到的记录不一致(第一次2条数据,第二次3条数据).
事务的隔离级别:
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。
Read committed:可避免脏读情况发生。
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
设置事务的隔离级别:
set transaction isolation level 设置事务隔离级别
select @@tx_isolation查询当前事务隔离级别
持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
事务是逻辑上的一组操作,组成这个操作的各个单元,要么全部成功,要么全部失败.
数据库开启事务命令:
Start transaction 开启事务
Rollback 回滚事务
Commit 提交事务
在 开启事务到提交事务之间的过程中,任何操作都可以用回滚来取消
JDBC事务控制方法:
Connection
setAutoCommit(false); 链接一般都是自动提交,所有要关掉自动提交.这就是开启事务
Rollback(); 回滚
Conn.commit; 提交
setSavePoint();设置回滚点
什么是数据库连接池?
以前每要与数据库建立一个链接,都要调用dao层给数据库发送一次请链接请求,如果链接的数量太多,数据库就会忙不过来,速度回非常慢,因此就需要数据库提供一个连接池,存放几个几个链接,以后dao就不会直接找数据库要链接,而是在连接池中建立链接.这样就减少了访问数据库的次数,提高了运行效率.
Dao每次从连接池中获取到一个Connection的时候,会把这个connection从池中提取出来,用完之后会把这个connection放回池中,如果要获取connection的dao请求数超过了池中的connection数,那么多出来的dao会等待一定的时间,如果在等待时间结束的时候,还没有connection被释放出来,那么就会提示等待的dao服务器忙.
DataSource:
里面维护了数据池,只要实现了这个接口,就称为标准的数据源.
一般要对一个已知类的方法进行加强,有三种方式:
1.包装类
包装设计模式步骤:
A.编写一个类,实现与被改写的类相同的借口
B.定义对原有类的引用
C.定义构造方法,接受被改写类的实例
D.改写需要改写的方法
E.对于不要改写的方法,调用原有类的方法
写包装类的时候,如果要实现的接口中有太多的方法要实现,那么可以使用适配器和包装类搭配使用.
适配器相当于一个特殊的包装类,只不过不改写接口的认可方法,只是实现. 而真正的包装类只要继承适配器,然后覆盖需要覆盖的方法即可.
//调用包装类的类 public class MyConnection extends MyDecorateWrapper { public MyConnection(Connection conn) { super(conn); } private static LinkedList<Connection> pool=new LinkedList<Connection>();//一个连接池 //初始化这个池 static{ Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { ResourceBundle rb=ResourceBundle.getBundle("dbcfig"); Class.forName(rb.getString("driverClass")); for (int i = 0; i < 10; i++) { conn=DriverManager.getConnection(rb.getString("url"), rb.getString("username"), rb.getString("password")); pool.add(conn); } } catch (Exception e) { // TODO: handle exception throw new RuntimeException(); } } //从连接池中获取连接 public static synchronized Connection getConnection(){ if(pool.size()>0){ Connection conn=pool.removeFirst(); return conn; }else { throw new RuntimeException("服务器忙!!"); } } @Override public void close() throws SQLException { // TODO Auto-generated method stub Connection conn=JdbcUtil.getConnection(); MyDecorate md=new MyDecorate(conn, pool); md.close();//这个就是包装类改写后的close方法 } } //包装类,继承适配器,只覆盖需要改写的方法 private static LinkedList<Connection> pool;//一个连接池 private Connection conn; public MyDecorate(Connection conn,LinkedList<Connection> pool) { super(conn); this.conn=conn; this.pool=pool; } @Override public void close() throws SQLException { // TODO Auto-generated method stub pool.addLast(conn); } //适配器 //一个适配器,和包装类相似,只不过不改写接口中的任何方法 public class MyDecorateWrapper implements Connection { private Connection conn; public MyDecorateWrapper(Connection conn){ this.conn=conn; } @Override public void clearWarnings() throws SQLException { // TODO Auto-generated method stub conn.clearWarnings(); } @Override public void close() throws SQLException { // TODO Auto-generated method stub conn.close(); } ......... |
3.动态代理
使用开源数据库连接池可以不用编写链接代码,只需要配置一些配置信息,然后调用内部的方法就行了.作用就是获取连接(Connection)
DBCP:
需要依赖两个jar包:
commons-dbcp.jar
commons-pool.jar
内部重载了两个获取连接的方法(getConnection),通常使用无参数的那一个.通过工厂得到实例,然后通过实例得到数据源(DataSource),通过数据源得到连接
DBCP工具类 private static DataSource ds; //数据源 static{ InputStream is=DBCPUtil.class.getResourceAsStream("dbcpconfig.properties"); Properties p=new Properties(); try { p.load(is); BasicDataSourceFactory factory=new BasicDataSourceFactory(); ds=factory.createDataSource(p); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //直接用 ds.getConnection);得到连接 |
依赖的jar包
c3p0-0.9.1.2.jar
c3p0-0.9.1.2-jdk1.3.jar
c3p0-oracle-thin-extras-0.9.1.2.jar(Oracle需要)
要使用C3P0就需要配置一个名为c3p0-config.xml的配置文件,c3p0配置文件可以配置多个数据库连接,只需要在<named-config name="">中配置要连接的数据库
配置好配置信息后,就可以用连接池建立链接了.
CombPooledDataSource ds = new ComboPoolesDataSource ("如果要连接指定数据库,就填入数据库名,前提是在xml中有配置"); |
TomCat内部用的就是DBCP连接池,其内部实现了数据源,要用Tomcat链接MySQL数据库,需要把数据库驱动(jar)拷贝到TomCat的lib包中.
配置数据源步骤:
1.把数据库驱动拷贝到TomCat中的lib目录下
2.在web应用中的WETA-INF目录下配置一个名为context.xml的配置文件,增加以下内容
<?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="jdbc/day14" auth="Container" type="javax.sql.DataSource" maxActive="20" maxIdle="10" maxWait="10000" username="root" password="sorry" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/day14"/> </Context> |
注:完成以上两个步骤,TomCat就会创建数据源 |
JNDI:Java命名与目录接口,它就是一个容器,通过特殊的方式根据名字(context.xml中的name属性)获取对象(数据库对象).
Context initContext = new InitialContext(); //固定写法 Context envContext = (Context)initContext.lookup("java:/comp/env"); //固定写法 DataSource ds = (DataSource)envContext.lookup("jdbc/day14"); //查找数据源 Connection conn = ds.getConnection(); //通过数据源得到链接 |
什么是元数据?
元数据就是数据库,数据表,数据列的信息.
获取数据库的元数据:
DataBaseMetaData .
//既然要获取数据库的元数据,当然是从连接中获得 Connection conn=DBCPUtil.getConnection(); DatabaseMetaData md=conn.getMetaData(); md.getDatabaseProductName(); |
ParmeterMetaData:
Connection conn=DBCPUtil.getConnection(); String sql="select * from emp"; PreparedStatement ps=conn.prepareStatement(sql); ParameterMetaData pmd=ps.getParameterMetaData();//得到数据表的元数据 |
ResultSetMetaData"
Connection conn=DBCPUtil.getConnection(); String sql="select * from emp"; PreparedStatement ps=conn.prepareStatement(sql); ResultSet rs=ps.executeQuery(); ResultSetMetaData smd=rs.getMetaData();//得到列的元数据 |
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
QueryRunner类 :
该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
QueryRunner类提供了两个构造方法:
默认的构造方法
需要一个 javax.sql.DataSource 来作参数的构造方法。
大文本操作
QueryRunner类的主要方法:
public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。
public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。(查询全部数据)
public int update(Connection conn, String sql, Object[] params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
public int update(Connection conn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。(全局操作)
ResultSetHandler接口
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
ResultSetHandler 接口的实现类
ArrayHandler:把结果集中的第一行数据转成对象数组。用于获取一条记录的情况下,把记录的每列数据,分装到了数组中.
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
ColumnListHandler:将结果集中某一列的数据存放到List中。
KeyedHandler(name):将结果集中的每一行数据都封装到一个Map<列名,列值>里,再把这些map再存到一个map里,其key为指定的key。
MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
JDBC一句话总结:
通过DBCP数据连接池或者C3P0数据连接池得到数据源,然后通过DBUtil来就行数据库操作.
相关文章推荐
- 黑马小日子--Servlet监听
- 黑马总结 三 : jdbc链接数据库
- 黑马小日子---servlet入门
- 黑马day10 jdbc入门&mysql
- 黑马的小日子--xml
- 黑马day10 jdbc抽取工具类
- 黑马的小日子--xml解析
- 黑马小日子--web服务
- 黑马小日子---servlet会话技术
- 黑马小日子----JSP
- 黑马就业班第五天-JDBC
- 【jdbc入门】_黑马day10听课笔记
- 黑马小日子--数据库基础
- 黑马小日子--文件上传
- 黑马作业(d29)JDBCUTils工具类
- 黑马小日子--过滤器
- Java jdbc数据库连接池总结
- oracle 11g JDBC连接数据库:IO异常The Network Adapter could not establish the connection 解决方法
- Jdbc插入date类型数据到oracle中
- java学习笔记:通过JDBC技术获取Oracle数据库连接