浅谈JDBC的概念理解与学习

开发 后端
本文将介绍JDBC的概念理解与学习的内容,JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

JDBC的概念:doMaim对象(javaBean实体)

UserDao(DataAccessObject)

工厂模式,Factory消除UserDaoTest业务类对具体实现UserDaoJdbc类的依赖

读配置文件,通过工厂读配置文件来加载信息,具体实现类使用工厂来获取实现接口类的对象

JDBC的概念:工厂一般使用单例模式

工厂-->生产产品(Dao这个产品)

类加载器,不光可以load.class,还可以load其他的文件

事务概念与处理

1.原子性:不能拆分,组成事事务处理的语句形成一个逻辑处理单元,不能只执行其中的一部分

2.一致性:事务做完之后,保定数据的完整性约束

3.隔离性:一个事务处理对另一个事务处理的影响

4.持续性:事务处理的结果能被***保存下来

步骤:打开事务connection.setAutoCommit(false);

提交事务:connection.commit();

回滚事务:connection.rollback();

jdbc缺省是自动提交的,客户端连接也是自动提交的,要想打开事务,要把自动提交关掉

保存点:savePoint

Savepointsp=null

sp=conn.setSavepoint();

conn.rollback(sp);

-----------------------------------

JDBC的概念:跨多个数据库的事务JTA

JTA容器weblogic,websphere

分成两阶段提交。

用到JNDI服务器

javax.transaction.UserTransactiontx=

(UserTransaction)ctx.lookup("jndiName");

tx.begin();

//connection1connection2(可能来自不同的数据库)

tx.commit();//tx.rollback();

---------------------------------

事务的隔离级别:

connction.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

隔离级别

读未提交(Readuncommitted)可能出现脏读,不可重复读,幻读

读已提交(Readcommitted)可能出现不可重复读,幻读

可重复读(Repeatableread)可能出现幻读(幻影数据,执行插入一条数据,在另一个客户端有可能看到)

可串行化(Serializable)

隔离级别各个数据库的实现是不一样的。

--------------------------------------------------

关于存储过程(两层架构的时候用的很多)

三层架构的系统很少使用了。略过不看了先。

---------------------------------------------------

其他几个有用的API

jdbc3.0规范提供的方法

插一条记录,它能把主键返回来

PreparedStatement.getGeneratedKeys();

PreparedStatementps=connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);

ps.executeUpdate();

ResultSetrs=st.getGeneratedKeys();

rs.getInt(1);

批量处理:可以大幅提升大量增删改的速度(并非绝对),与具体数据库有关,也不一定能提高性能

PreparedStatement.addBatch();

PreparedStatement.executeBatch();

 

-------------------------------------------------------------

可滚动结果集与分页特性

Statementst=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

ResultSet.TYPE_SCROLL_SENSITIVE--对数据库敏感的,就是说,数据库中记录发生了变化,结果集会觉察到(但某些数据库不一定遵循这一规范,mysql就不遵循)

ResultSet.CONCUR_UPDATABLE--可更新的,就是说,改变结果集中的内容可以影响到数据库里

ResultSet.CONCUR_READ_ONLY--只读的,

可滚动的结果集

Statementst=connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

ResultSetrs=st.executeQuery(sql);

rs.beforeFirst();

rs.afterLast();

rs.first();

rs.isFirst();

rs.last();

rs.isLast();

rs.absolute(9);

rs.moveToInsertRow();

conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

rs.updateString("colname","newvalue");

rs.updateRow();

mysql分页例如:

selectid,name,money,birthdayfromuserlimit150,10;

从user表中第150条记录开始,取10条记录

---------------------------------------------------------

jdbc元数据信息数据库元数据信息、参数元数据信息

DatabaseMetaDatameta=connection.getMetaData();

通过DatabaseMetaData可以获得数据库相关的信息,如:

数据库版本,数据库名,数据库厂商信息,是否支持事务,是否支持某种事务隔离级别,

是否支持滚动结果集等。

ParameterMetaDatapmd=preparedStatement.getParameterMetaData();

通过ParameterMetaData可以获得参数信息.

ParameterMetaDatapmd=ps.getParameterMetaData();

intcount=pmd.getParameterCount();

System.out.println("count="+count);

for(inti=1;i<=count;i++)

{

ps.setObject(i,params[i-1]);

}

ResultSetrs=ps.executeQuery();

--------------------------------------------------

dataSource代理模式:

组合优先于继承

拦截Connection.close()方法

动态代理

调用处理器

----------------------------------------------------

数据源和连接池

DataSource用来取代DriverManger来获取Connection

通过DataSource获得Connection速度很快

通过DataSource获得的Connection都是已经被包裹过的(不是驱动原来的连接),

他的close方法已经被修改

一般DataSource内部会用一个连接池来缓存Connection,这样可以大幅度提高

数据库的访问速度;

连接池可以理解成一个能够存放Connection的Connection

我们的程序只和DataSource打交道,不会直接访问连接池。

------------------------------------------

DBCP的应用

1.加载三个.jar

2.写dbcpconfig.properties配置文件

3.创建DataSource数据源

使用DBCP必须用的三个包

commons-dbcp-1.2.2\commons-dbcp-1.2.1.jar,

spring-framework-2.5.6\lib\jakarta-commons\commons-pool.jar,commons-collection-3.1.jar

dbcpconfig.properties

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc

username=root

password=root

#初始化连接

initialSize=10

#***连接数量

maxActive=50

#***空闲连接

maxIdle=20

#最小空闲连接

minIdle=5

#超时等待时间以毫秒为单位

maxWait=60000

#JDBC驱动建立连接时附带的连接属性格式必须为这样:属性名=property

#注注意user与password两个属性会被明确地传递。因此这里不需要包含他们

connectionProperties=useUnicode=true;characterEncoding=utf-8

#指定由连接池所创建的连接的自动提交auto-commit状态

defaultAutoCommit=true

#driverdefault指定由连接池所创建的连接的只读read-only状态

#如果没有设置该值,则setReadOnly方法不被调用。

defaultReadOnly=

#driverdefault指定由连接池所创建的连接的事务级别TransactionIsolation

#可用值为下列之一:这依赖于数据库

#NONE,READ_UNCOMMITED,READ_COMMITTED

defaultTransactionIsolation=READ_COMMITTED

 

----------------------------------------------------

创建数据源

Propertiesprop=newProperties();

prop.setProperty("driverClassName","com.mysql.jdbc.Driver");

prop.setProperty("url","jdbc:mysql://localhost:3306/jdbc");

prop.setProperty("username","root");

prop.setProperty("password","root");

#dbcp使用这个方法创建数据源,需要一个Property参数,参数中的键值对就为.properties文件中的配置

#可以直接load进来,省的写了

Propertiesprop=newProperties();

InputStreamis=JdbcUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

prop.load(is);

DataSourcemyDataSource=BasicDataSourceFactory.createDataSource(prop);

-------------------------------------------------------------------------

模板模式对查询抽象,采用继承的方式(对查询来说,不够灵活,查询的列一变化,就得修改超类)

策略模式(采用接口的方式传递一个接口的参数,通过匿名类为各种需求实现)

-----------------------------------------------------------------------

使用JdbcTemplate工具类,在spring框架中提供了一个JdbcTemplate工具类,这个类对JDBCAPI进行了很好的封装

这个类就像我们自己对JDBC进行封装一样。只是代码列健壮,功能更强大而已。

我们以后在实际项目中可以使用JdbcTemplate类来完全替代直接使用JDBCAPI这与直接使用jdbcapi没有太大性能区别

使用JdbcTemplate工具类需要额外从spring开发包中导入spring.jar和commons-logging.jar

关于jdbcTemplate查询,更新相关使用方法见练习

如果想获取connection,自由进行操作,可以使用

  1. jdbc.execute(newConnectionCallback()  
  2. {  
  3.  
  4. publicObjectdoInConnection(Connectionconn)throwsSQLException,  
  5. DataAccessException  
  6. {}  
  7. });//拿到了Connction随你怎么用了  
  8.  
  9. -------------------------------------------------------------------  
  10. Spring的NameParameterJdbcTemplate  
  11. NameParameterJdbcTemplate内部包含了一个JdbcTemplate,所以JdbcTemplate能做的事情它都能做  
  12. NameParameterJdbcTemplate相对于JdbcTemplate主要增加了参数可以命名的功能  
  13.  
  14. publicObjectqueryForObject(Stringsql,MapparamMap,RowMapperrowMapper)  
  15. publicObjectqueryForObject(Stringsql,SqlParameterSourceparamSource,RowMapperrowMapper) 

#p#

SqlParameterSource的两个主要实现MapSqlParameterSource和BeanPropertyParameterSource

SimpleJdbcTemplate内部包含了一个NamedParameterJdbcTemplate,所以NamedParameterJdbcTemplate

能做的事情SimpleJdbcTemplate都能干,SimpleJdbcTemplate相对于NamedParameterJdbcTemplate主要

增加了JDK5.0的泛型技术和可变长度参数支持

simpleJdbcTemplate中有些方法不全,比如拿到主键的方法就没有,可以获取到NamedParameterJdbcTemplate

调用它里面的方法

getNamedParameterJdbcOperations()返回的是NamedParameterJdbcOperations其实现就是NamedParameterJdbcTemplate这个类

getJdbcOperations()返回的是JdbcOperation其实现就是JdbcTemplate

++++++++++++++++++++++++++++++++++++++++++++++++++

Map参数源:采用键值对方式传参(参数别名可任意,如:m,:n)

  1. staticUserfindUser(Useruser)  
  2. {  
  3. NamedParameterJdbcTemplatenamed=newNamedParameterJdbcTemplate(dataSource);  
  4. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:mandid<:n";  
  5. Mapmap=newHashMap();  
  6. map.put("m",user.getMoney());  
  7. map.put("n",user.getId());  
  8. Objectu=named.queryForObject(sql,map,newBeanPropertyRowMapper(User.class));//这个方法当查询对象多于一个或为null时会抛异常  
  9. return(User)u;  

Bean属性参数源使用方法(参数别名要与bean类的属性对应,如:money,:id)(通过&号也可以命名别名,不建议使用)

  1. staticUserfindUser(Useruser)  
  2. {  
  3. NamedParameterJdbcTemplatenamed=newNamedParameterJdbcTemplate(dataSource);  
  4. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:moneyandid<:id";  
  5. SqlParameterSourceps=newBeanPropertySqlParameterSource(user);  
  6.  
  7. Objectu=named.queryForObject(sql,ps,newBeanPropertyRowMapper(User.class));//这个方法当查询对象多于一个或为null时会抛异常  
  8. return(User)u;  
  9. //保存数据获得主键

    publicintupdate(Stringsql,SqlParameterSourceparamSource,KeyHoldergeneratedKeyHolder)staticvoidaddUser(Useruser)

    {

    NameParameterJdbcTemplatenamed=newNameParameterJdbcTemplate(dataSource);

    Stringsql="insertintouser(name,birthday,money)values(:name,:birthday,:money";

    SqlParameterSourceps=newBeanPropertySqlParameterSource(user);

    KeyHolderkeyHolder=newGeneratedKeyHolder();

    named.update(sql,ps,keyHolder);

    intid=keyHolder.getKey().intValue();user.setId(id);//如果不是整型的主键呢,使用Mapmap=keyHolder.getKeys();}

JDBC的概念:使用泛型技术与可变长度的参数(JDK1.5版本以上)

  1. //泛型技术(JDK1.5以上版本可使用)  
  2. //使用泛型技术与可变长度的参数(JDK1.5版本以上)  
  3. staticUserfindUserSimple(Stringname)  
  4. {  
  5. SimpleJdbcTemplatesimple=newSimpleJdbcTemplate(JdbcUtil.getDataSource());  
  6.  
  7. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:moneyandid<:id";  
  8.  
  9. //用这个泛型,返回结果就不用向下转型了  
  10. //publicTqueryForObject(Stringsql,ParameterizedRowMapperrm,Object...args)throwsDataAccessException  
  11. Useru=simple.queryForObject(sql,  
  12. ParameterizedBeanPropertyRowMapper.newInstance(  
  13. User.class),name);//这个行映射器的参数是可变长的Object...  
  14. returnu;  
  15. }  
  16.  
  17.  
  18. -----------------------------------------------------------------------------------------------------------------------  
  19. //代码  
  20.  
  21. importjava.util.HashMap;  
  22. importjava.util.Map;  
  23.  
  24. importorg.springframework.jdbc.core.BeanPropertyRowMapper;  
  25. importorg.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;  
  26. importorg.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;  
  27. importorg.springframework.jdbc.core.namedparam.SqlParameterSource;  
  28.  
  29. importcom.feihu.domain.User;  
  30. importcom.feihu.jdbc.JdbcUtil;  
  31.  
  32. publicclassSimpleJdbcTemplate  
  33. {  
  34. privatestaticNamedParameterJdbcTemplatenamed=newNamedParameterJdbcTemplate(  
  35. JdbcUtil.getDataSource());  
  36.  
  37. ///参数命名方法查询NamedParameterJdbcTemplate  
  38. //两种参数传递方法BeanPropertySqlParameterSource(user)、MapSqlParameterSource  
  39.  
  40. //bean属性参数源  
  41. staticUserfindUser(Useruser)  
  42. {  
  43. //Bean属性参数源使用方法(参数别名要与bean类的属性对应,如:money,:id)(通过&号也可以命名别名,不建议使用)  
  44.  
  45. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:moneyandid<:id";  
  46. SqlParameterSourceps=newBeanPropertySqlParameterSource(user);  
  47.  
  48. Objectu=named.queryForObject(sql,ps,newBeanPropertyRowMapper(  
  49. User.class));//这个方法当查询对象多于一个或为null时会抛异常  
  50. return(User)u;  
  51. }  
  52.  
  53. //Map参数源  
  54. staticUserfindUser2(Useruser)  
  55. {  
  56. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:mandid<:n";  
  57. Mapmap=newHashMap();  
  58. map.put("m",user.getMoney());  
  59. map.put("n",user.getId());  
  60. Objectu=named.queryForObject(sql,map,newBeanPropertyRowMapper(  
  61. User.class));//这个方法当查询对象多于一个或为null时会抛异常  
  62. return(User)u;  
  63. }  
  64.  
  65. //泛型技术(JDK1.5以上版本可使用)  
  66. //使用泛型技术与可变长度的参数(JDK1.5版本以上)  
  67. staticUserfindUserSimple(Stringname)  
  68. {  
  69. SimpleJdbcTemplatesimple=newSimpleJdbcTemplate(JdbcUtil.getDataSource());  
  70.  
  71. Stringsql="selectid,name,money,birthdayfromuserwheremoney>:moneyandid<:id";  
  72.  
  73. //用这个泛型,返回结果就不用向下转型了  
  74. //publicTqueryForObject(Stringsql,ParameterizedRowMapperrm,Object...args)throwsDataAccessException  
  75. Useru=simple.queryForObject(sql,  
  76. ParameterizedBeanPropertyRowMapper.newInstance(  
  77. User.class),name);//这个行映射器的参数是可变长的Object...  
  78. returnu;  
  79. }  

【编辑推荐】

  1. 使用JDBC的五个精华功能
  2. Tomcat5+MySQL JDBC连接池配置
  3. 在Weblogic中实现JDBC的功能
  4. 详解JDBC与Hibernate区别
  5. JDBC连接MySQL数据库关键四步
  6. 浅谈JDBC DAO的设计理念
责任编辑:彭凡 来源: 新浪科技
相关推荐

2010-09-13 14:34:55

2009-07-01 17:58:20

JSP

2009-08-20 19:08:30

C#异步调用

2017-05-02 14:45:11

深度学习机器学习人工神经网络

2009-07-15 15:47:12

JDBC DAO

2009-06-24 11:12:17

callerJavascript

2009-07-23 13:30:46

JDBC事务

2010-06-30 17:34:25

SNMP Trap

2009-06-29 17:17:57

Spring

2009-07-21 17:41:58

JDBC数据源

2015-12-10 09:24:54

Linux架构理解

2009-06-17 15:25:59

Java学习

2021-08-29 23:25:36

前端开发工具

2009-07-20 17:41:59

Java JDBC

2009-07-14 17:01:24

JDBC基础

2017-05-22 16:00:14

2018-09-29 10:05:54

深度学习神经网络神经元

2010-01-07 13:27:15

JSON概念

2010-01-26 17:42:14

Android浮点

2009-06-19 13:37:53

Spring JDBC
点赞
收藏

51CTO技术栈公众号