由浅到深学习JDBC三

JDBC6.0最终版。

数据访问层Dao

业务逻辑层service

我们在Dao层中封装了对表的常用操作,增删改查。

我们在Util里封装了JDBCUtil工具类解决冗余问题。

现在我们有一个银行转账问题:

1.根据卡号,密码,先查询

2.转出账户再余额足够的情况下,减去转出资金。

3转入账户添加转入资金。

对于2,3步骤我们因当把他们看作是一个事务,事务的原子性,一致性,隔离性。要求

要么一起成功,要么一起不成功。当然从现实考虑,也确实应当这样,如果在2,3步骤之间失败了

就回退。

这整个转账逻辑,我们可以称之为业务。所以针对软件的三层结构。我们把这部分称为-----业务层(service)

在service层调用Dao层的方法。

而在service层里的连接对象和Dao层里的连接对象不是同一个对象,这就会造成混乱,打破事务的一致性。

从而导致,转出钱减去了,转入账户没加钱。

Service方法中的事务控制失败。

原因:service控制事务时过的conn和DAO访问数据库使用的conn时两个不同对象

解决:

保证service和Dao使用同一个conn对象

1:通过参数传递。

2:每个线程对象有一个Map属性,可以存储数据

在service获得conn,将conn放入当前Thread对象,在DAO访问数据库时取时,从Thread取出conn

ThreadLocal简介及使用:

操作当前线程对象中的一小块空间。

1创建ThreadLocal对象 ThreadLocal<Connection> tdl = new ThreadLocal<Connection>();

2tdl.set(conn);将conn添加到当前线程。

3tdl.get();获得当前线程中的数据

4tdl.remove()移除当前线程里的数据

话不多说我们来看代码有三个文件 JDBC_Util3.java JDBC_Dao3.java JDBC_Service.java

JDBC_Util3.java

public class JDBC_Util3 {

private static final Properties prop = new Properties();

private static final ThreadLocal<Connection> tdl = new ThreadLocal<Connection>();

static{

InputStream is = null;

try {

is = JDBC_Util3.class.getResourceAsStream("jdbc.properties");

prop.load(is);

String driverName = prop.getProperty("driverName");

Class.forName(driverName);

catch (Exception e) {

e.printStackTrace();

}

}

//返回链接

public static Connection getConnection() throws Exception {

Connection conn = null;

conn = tdl.get();//获得当前线程连接

if(conn == null){

//说明当前线程没有conn

String user = prop.getProperty("user");

String password = prop.getProperty("password");

String url = prop.getProperty("url");

conn = DriverManager.getConnection(url,user,password);

//将当 conn存入线程

tdl.set(conn);

}

return conn;

}

/**

* 释放资源

*/

public static void release(ResultSet rs,Statement stm,Connection conn){

try {

if(rs!=null){rs.close();}

if(stm!=null){stm.close();}

if(conn!=null){

conn.close();

tdl.remove();//移除当前线程对象中的conn

}

catch (SQLException e) {

e.printStackTrace();

}

}

}

JDBC_Dao3.java

public class JDBC_Dao3 {

/ /更新账户

public void upDateAccount(Account toAcc) {

Connection conn = null;

PreparedStatement pstm = null;

try {

conn = JDBC_Util3.getConnection();

String sql = "update account set card_id=?,"

+ "password=?,balance=?,phone=? where card_id=?";

pstm = conn.prepareStatement(sql);

pstm.setString(1, toAcc.getCardId());

pstm.setString(2, toAcc.getPassword());

pstm.setDouble(3, toAcc.getBalance());

pstm.setString(4, toAcc.getPhone());

pstm.setString(5, toAcc.getCardId());

int i  = pstm.executeUpdate();

catch (Exception e) {

e.printStackTrace();

}finally{

JDBC_Util.release(null, pstm, null);

}

}

// 查询账户

public Account queryAccount(Integer toCardId) {

Connection conn = null;

Statement stm = null;

ResultSet rs = null;

Account acc = null;

try {

conn = JDBC_Util3.getConnection();

stm = conn.createStatement();

String sql = "select * from account where card_id = "

+ toCardId;

System.out.println(sql);

rs = stm.executeQuery(sql);

while (rs.next()) {

acc = new Account();

acc.setCardId(rs.getString("card_id"));

acc.setPassword(rs.getString("password"));

acc.setBalance(rs.getDouble("balance"));

acc.setPhone(rs.getString("phone"));

}

catch (Exception e) {

}finally{

JDBC_Util.release(rs, stm, null);

}

return acc;

}

}

JDBC_Service.java

public class JDBC_Service {

public void transfer(Integer fromCardId,String password,

Integer toCardId,Double money){

Connection conn = null;

try{

conn = JDBC_Util2.getConnection();

//事务自动提交关闭

conn.setAutoCommit(false);

JDBC_Dao3 dao = new JDBC_Dao3();

//验证卡号是否存在

Account fromAcc = dao.queryAccount(fromCardId);

if(fromAcc == null){

throw new RuntimeException("卡号不存在");

}

//验证密码是否正确

if(null==password||!password.equals(fromAcc.getPassword())){

throw new RuntimeException("密码错误");

}

//验证余额

if(fromAcc.getBalance()<money){

throw new RuntimeException("余额不足");

}

//转出账户更新

fromAcc.setBalance(fromAcc.getBalance()-money);

dao.upDateAccount(fromAcc);

Account toAcc = dao.queryAccount(toCardId);

//验证到账卡号

if(toAcc ==null){

throw new RuntimeException("到账卡号不存在");

}

//转入账户更新

toAcc.setBalance(toAcc.getBalance()+money);

dao.upDateAccount(toAcc);

//提交事务

conn.commit();

}catch(Exception e){

e.printStackTrace();

try {

conn.rollback();

catch (SQLException e1) {

e1.printStackTrace();

}

}finally{

JDBC_Util.release(nullnull, conn);

}

}

}

最后main函数测试

JDBC_Service sv =  new JDBC_Service();

sv.transfer(10002, "123321", 10004, 30.00);

转账成功

10002 -30  10004 +30

=========================华丽丽的终结===========================

总结:虽然由于快节奏的开发,编程速度的追求,越爱越多的MVC框架出现,比如持久层的hibernate,

mybatis等等,他们对Dao层的支持都很强大,既 快速,又简便。但是他们的底层同样是使用了JDBC,

为了追求高速简便,我们可以不使用JDBC,但一定要了解JDBC。了解JDBC也有助于学习其他持久层框架。

以上就是我对JDBC全部心得。

限于文章篇幅原因,这里仅仅介绍冰山一角。由于笔者的水平有限,编写时间也很仓促,

文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。

时间: 2024-10-13 06:32:54

由浅到深学习JDBC三的相关文章

由浅到深学习JDBC二

封装数据访问对象 1:通过分析总结,所有对数据库表的操作都可以总结为通过JDBC对表的增删改查,为了减少冗余代码, 使得每次操作表时,不必都写JDBC程序,所以将对一张表的所有数据访功能,封装在数据访问对象 (Data Access Object)中,方便调用. 2:为了方便数据传输,往往会将java程序中所有相关操作的零散字段值,封装成一个实体对象--entity. 实体封装原则: 表----实体类 字段---属性 实现序列化 提供set,get方法. 以下代码就是利用Dao数据访问对象写出的

由浅到深学习JDBC一

JDBC: 虽然由于快节奏的开发,编程速度的追求,越爱越多的MVC框架出现,比如持久层的hibernate, mybatis等等,他们对Dao层的支持都很强大,既快速,又简便.但是他们的底层同样是使用了JDBC, 为了追求高速简便,我们可以不使用JDBC,但一定要了解JDBC.了解JDBC也有助于学习其他持久层框架. java和数据库交互需要中间程序作为中转.在很早以前,数据库厂商还没有一套统一的API作为 java语言和数据库的接口,开发程序是一件很头疼的事.对不同的数据库需要写不同的程序来作

由浅至深学习block

关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想到在C函数中,我们可以定义一个指向函数的指针并且调用: bool executeSomeTask(void) {     //do something and return if success or not } bool (*taskPoint)(void); taskPoint = something; 上面的函数指针可以直接通过(*taskPo

iOS开发-由浅至深学习block

关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想到在C函数中,我们可以定义一个指向函数的指针并且调用: 1 2 3 4 5 bool executeSomeTask(void) {     //do something and return if success or not } bool (*taskPoint)(void); taskPoint = something; 上面的函数指针可以直接

javaweb学习总结(三十三)——使用JDBC对数据库进行CRUD

javaweb学习总结(三十三)——使用JDBC对数据库进行CRUD 一.statement对象介绍 Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可. Statement对象的executeUpdate方法,用于向数据库发送增.删.改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化). Statement.executeQuery方法用于向数据库发

javaweb学习总结(三十二)——JDBC学习入门【转】

原文地址:javaweb学习总结(三十二)——JDBC学习入门 一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后 才能够使用声卡和网卡,同样道理,我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数 据库打交道,如下所示: 1.2.JDBC介绍 SUN公司为了简化.统一对数据库的操作,定义了一套Java操作

javaweb学习总结(三十二)——JDBC学习入门

一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡,同样道理,我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道,如下所示: 1.2.JDBC介绍 SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC.这套接口由数据库厂商去实现,这

浅入深出ElasticSearch构建高性能搜索架构

浅入深出ElasticSearch构建高性能搜索架构  课程学习地址:http://www.xuetuwuyou.com/course/161 课程出自学途无忧网:http://www.xuetuwuyou.com 一.课程用到的软件 ElasticSearch5.0.0 Spring Tool Suite 3.8.2.RELEASE Maven3.0.5 Spring4 Netty4 Hadoop2.7.1 Kibana5.0 JDK1.8.0_111 二.课程目标 1.快速学习Elastic

python 学习笔记 三 字典

字典 Python的高效的key/value哈希表结构叫做"dict", dict的内容可以写成一系列的key:value对并放入{ }中, 相当于: dict = {key1:value1, key2:value2, ...}, 一个空的字典就是俩个大括号{ }. 下面是从一个空字典创建字典以及一些关键点: 数字, 字符串和元组可以作为字典的key, value可以是任何类型(包括字典). ## Can build up a dict by starting with the the