JavaWeb之JDBC&自定义框架/DBUtil(十五)

简介

关于代码方面,可能在今后博客中很少写,因为我尽量把代码体现成思路出来。以便以后复习看着思路写代码。其实代码成篇贴上去也未必有心思看下去,不如思路来得实际

自定义框架

1. 编写简单自定义框架,简化数据访问层操作

1. 准备环境
	1.1 jar包	c3p0-0.9.1.2.jar/mysql-connector-java-5.0.8-bin.jar
	1.2 需要获取数据源(这里使用c3p0获取)C3P0Util.java/相应的配置文件c3p0-config.xml

2. 	开发简单框架简化DAO操作DBAssist类
	1>. 降低依赖性,这里数据源获取由外部传入,由构造接收对成员属性进行赋值
		private static DataSource ds;
		public DBAssist(DataSource ds) {
			this.ds = ds;
		}
3. 因为CUD操作方式一样,唯一不一样的是参数个数,所以这里可以定义一个方法对CUD进行操作
	定义方法void update(String sql, Object...params)
		3.1 通过数据源获取数据库连接
		3.2 获取执行sql语句对象
		3.3 通过该对象获取参数元数据信息
			ParameterMetaData rsmd = stmt.getParameterMetaData();
			得到参数个数int count = rsmd.getParameterCount();
		3.4 判断参数个数是否与objs对应的参数值是否一致
			1). 首先判断参数个数(count)是否大于0
			2). 判断接收的参数是否为空或小于0/再判断接收的参数和参数个数是否相等
			3). 否则匹配条件,则遍历参数,对每个参数进行赋值(值为接收的参数)
		3.5 执行语句	stmt.executeUpdate();
		3.6 释放资源		C3P0Util.release(null, stmt, conn);

4. 查询结果集
		定义方法Object query(String sql,ResultSetHandler rsh ,Object...params)
		重复3.1-3.4步骤
		4.5 执行结果集stmt.executeQuery();
		4.6 将结果集转成Object对象返回

5. 	延续4.6步骤将结果集转成Object对象返回
	5.1 建立接口ResultSetHandler,结果处理器这种模式就是策略设计模式,抽象策略
		public interface ResultSetHandler {
			Object handler(ResultSet rs);
		}
	5.2 建立与数据库相应的JavaBean类
	5.3 建立BeanHandler类,适用于结果集只有一条记录的情况,如果结果集有多条记录,只返回第一条要封装的目标类型,需要调用者传回来,JavaBean的字段名与数据库列名保持一致和对应,而且JavaBean有默认构造方法
		使用装饰对要注入的类进行接收
			private Class clazz;
			public BeanHandler(Class clazz) {
				this.clazz = clazz;
			}
	5.4 将结果集转换对象的方法Object handler(ResultSet rs)
		1). 首先创建要注入类的实例	obj = clazz.newInstance();
		2). 获取结果集的元信息,通过元信息获取个数
			ResultSetMetaData rsmd = rs.getMetaData();
			int count = rsmd.getColumnCount();
		3). 遍历每个参数
			获取列名和列值
					String columnName = rsmd.getColumnName(i+1);
					Object columnValue = rs.getObject(i+1);
			通过反射将列值设置到注入类的属性中
				Field field = clazz.getDeclaredField(columnName);
				field.setAccessible(true);
				field.set(obj, columnValue);

6. 查询所有结果集BeanListHandler和查询单个结果集唯一不同的是需要定义一个集合
	6.1 定义集合用作存储每个结果集
	6.2 区别1,将if修改为while,就是代表遍历每一行数据
	6.3 将每一行的结果集添加到list集合中

ORM(对象关系映射)

1. ORM是什么?

ORM(Object/Relation Mapping)就是对象-关系的映射,对象就是Java这种面向对象语言,关系就是关系型数据库,其实就是把一个对象映射成表的一行记录,再把表的一行记录映射成Java中的一个对象。这就是ORM的用途!

2. ORM是什么?

1. Apache commons DBUtils:很简单的JDBC框架,很多公司在使用它,就是因为它内容很简单,也很方便;
2. Hibernate(全自动):SSH中的H就是它了,它的HQL号称是面向对象的查询语言;
3. Ibatis(半自动):简单、方便!很多人用“全自动”形容Hibernate,那么对Ibatis就是“半自动”了。Hibernate把面向关系的东西都封装起来了,甚至你可能对SQL不是很了解都可以通过Hibernate来操作数据库!但是,有是我们还是需要自己来通过面向关系(打开封装)来完成一些特殊的操作,那么“半自动”的Ibatis就派上用场了;
4. Spring-JDBC(基本与DBUtils是一个级别的,很简单的封装):Spring中的JDBC框架与dbUtils很相似!但是Spring的IoC给Spring-JDBC做了强大的后盾,并且Spring通过AOP对声明式事务的处理可以说是为人能比,所以,Spring的JDBC框架还是很有用途的;
5. EJB(Entity Bean)(老了):Java EE中的实体Bean,因为是重量级组件,现在已经很少使用了。
 

DBUtils

1 DBUtils简介

DBUtils是Apache Commons组件中的一员,开源免费!
DBUtils是对JDBC的简单封装,但是它还是被很多公司使用!
DBUtils的Jar包:dbutils.jar

2 DBUtils简介

DbUtils:都是静态方法,一系列的close()方法;
QueryRunner:提供update()、query()、batch()方法;

QueryRunner的query()方法也需要ResultSetHandler来映射结果集

1. 批处理使用:
	public void testBatch() {
		Object[][] params = new Object[10][];
		for(int i=0; i<params.length; i++) {
			params[i] = new Object[]{i,"web"+i,1000.00f};
		}
		try {
			qr.batch("insert into t3 values(?,?,?)",params);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

2. query常用三种使用:
	2.1 public void testBeanHandler() {
			Account a = new Account();
			a = qr.query("select * from t4 where id=?", new BeanHandler(a.getClass()),1);
			System.out.println(a);
		}
	2.2 public void testBeanListHandler() {
			List<Account> accounts = new ArrayList<Account>();
			accounts = qr.query("select * from t4", new BeanListHandler<Account>(Account.class));
			System.out.println(accounts);
		}
	2.3 public void testScalarHandler2() {
			int totalRecordes =  ((Long) qr.query("select count(*) from t3", new ScalarHandler())).intValue();
			System.out.println(totalRecordes);	//获取总条数,分页时使用
		}

3 DBUtils与事务处理

con.setAutoCommit(false); -- 开始
con.commit(); -- 成功结束
con.rollback(); -- 失败结束

事务与DBUtil简单使用,下面一个示例会加深理解,这里只作简单理解
private QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());

public void transfor(int sourceAcc, int targetAcc, float money) {
	Connection conn = null;
	try {
		conn = C3P0Util.getConnection();
		conn.setAutoCommit(false);
		qr.update("update account set money=money-? where id=?", money,
				sourceAcc);
		int i = 1/0;
		qr.update("update account set money=money+? where id=?", money,
				targetAcc);

		conn.commit();
	} catch (Exception e) {
		if(conn != null) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
	}
}

4 Dao和Service中的事务处理(实现用户转账)

1. 开发前奏
	1.1 导包/获取数据源工具类,接口,不再重复
	1.2 步骤JavaBean类-->AccountDaoImpl-->BusinnesServiceImpl<-->BeanFactory<-->TransactionManager

2. 建立账户类(Account)和数据库账户表中字段信息成映射关系
	private int id;
	private String name;
	private float money;

3. 数据访问层专注操作数据中的实现类AccountDaoImpl
	3.1 使用DBUtil实现获取账户和更新账户功能
		1). private QueryRunner qr = new QueryRunner();
		2). Account getAccountById(int id)/ void updateAccount(Account acc)
		3). 在查询或者更新时指定连接确保是一个数据库连接(这里需要用事务管理中的方法)

4. 业务逻辑层专注业务操作BusinnesServiceImpl
	1. 获取dao层对象对数据操作
	2. 通过姓名获取要转账的账户(源和目的账户)
	3. 对账户余额进行操作
	4. 写入到表中updateAccout()

5. 代理业务逻辑层的实现类,实现业务层专注操作业务部分,其他功能由代理对象代理,当使用业务逻辑类时,直接使用代理对象即可
	1. 定义代理的对象
	2. 通过动态代理中Proxy类中newProxyInstance(ClassLoader, Interfaces, InvocationHandler)创建代理类
		1). 对业务方法采采用相应的策略
			if("transfor".equals(method.getName())) {
				try {
					//横向切入要添加的事务
					TransactionManager.startTransaction();//又称前置通知
					//保证原有方法能执行
					Object retVal = method.invoke(service, args);
					//后置通知
					TransactionManager.startTransaction();
					//最终勿忘将代理的对象返回
				} catch (Exception e) {
						e.printStackTrace();
						TransactionManager.rollback();//异常通知
				}
				//finally 最终通知
			}

6. TransactionManager类,上一步骤提到的事务,应封装到一个事务管理类,专注事务处理
	当前线程存入的线程局部变量只能当前线程取值
	其他线程是取不了的
	1. 定义线程局部变量,用于放连接
		private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
	2. 获取连接方法,将连接设置到线程局部变量中
	3. startTransaction()/rollback()/commit()
		先获取连接,在执行相应的操作
时间: 2024-11-03 03:30:45

JavaWeb之JDBC&自定义框架/DBUtil(十五)的相关文章

应用程序框架实战十五:DDD分层架构之领域实体(验证篇)

在应用程序框架实战十四:DDD分层架构之领域实体(基础篇)一文中,我介绍了领域实体的基础,包括标识.相等性比较.输出实体状态等.本文将介绍领域实体的一个核心内容——验证,它是应用程序健壮性的基石.为了完成领域实体的验证,我们在前面已经准备好了验证公共操作类和异常公共操作类. .Net提供的DataAnnotations验证方法非常强大,Mvc会自动将DataAnnotations特性转换为客户端Js验证,从而提升了用户体验.但是客户端验证是靠不住的,因为很容易绕开界面向服务端提交数据,所以服务端

laravel框架总结(十五) -- 发送邮件

laravel自带SwiftMailer库,集成了多种邮件API,支持多种邮件驱动方式,包括smtp.Mailgun.Maildrill.Amazon SES.mail和sendmail,Mailgun和Amazon SES都是收费的,Maildrill目前不支持中国区用户,这三个都是第三方邮件服务.mail驱动使用PHP提供的mail函数发送,sendmail驱动通过Sendmail/Postfix(Linux)提供的命令发送邮件,smtp驱动通过支持ESMTP的SMTP发送邮件.就目前状况来

Django框架(十五)—— Django分页组件

Django分页组件 一.分页器 数据量大的话,可以分页获取,查看 例如:图书管理中,如果有成千上万本书,要是都在一个页面中渲染出来,会影响页面美观,所以就要用分页器分页渲染 二.分页器的使用 基本写法 基本写法: 后端: 总数据拿出来 生成分页器Paginator对象(对象里有属性和方法) 生成当前页的对象,current_page=paginator.page(当前页码) 取出前台传过来的页码,current_page_num = int(request.GET.get('page')) -

Django框架(十五)-- cookie和session组件

一.cookie 1.cookie的由来 HTTP协议是无状态的.无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况. 客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留.会话中产生的数据又是我们需要保存的,也就是说要“保持状态”.因此Cookie就是在这样一个场景下诞生. 2.什么是cookie 存储在客户端浏览器上的键值对. 随着服务器端的响应发送给客户端浏览器.

Python之路【第十五篇】:Web框架

Python之路[第十五篇]:Web框架 Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #!/usr/bin/env python #coding:utf-8   import socket   def handle_request(client):     buf = client.recv(10

第二十五天 慵懒的投射在JDBC上的暖阳 —Hibernate的使用(四)

6月4日,晴天."晴日暖风生麦气,绿阴幽草胜花时."      "道"是只有中国人才懂得并孜孜以求的特殊的宇宙存在感的体验.全世界只有中文才能阐释"道"的全部涵义.然而所谓阐释,并不重在定义,更多的还是感受. "道"既在"虚无"之内,又超越了"虚无",成为中国文化最平常但又最玄妙的一种境界. 老庄认为:道是宇宙的本体,即是宇宙万物的老祖宗.    老外认为:Tao is the sour

十五天精通WCF——第九天 高级玩法之自定义Behavior

原文:十五天精通WCF--第九天 高级玩法之自定义Behavior 终于我又看完了二期爱情保卫战,太酸爽了,推荐链接:http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd,不多说,谁看谁入迷,下面言归正传, 看看这个很有意思的Behavior. 一: Behavior这个泼妇的厉害   在前面的文章中,我也清楚的说明了整个wcf通信流,而Behavior这个泼妇可以在wcf通信流中的任何地方插上一脚,蛮狠无比,利用的好,让你上天堂,利用的不

JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine

JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇幅讲 一.文本复制 读写都说了,我们来看下其他的操作,我们首先来看复制 复制原理:其实就是将C盘下的文件数据存储到D盘的一个文件中 实现的步骤: 1.在D盘创建一个文件,用于存储文件中的数据 2.定义读取流和文件关联 3.通过不断的读写完成数据的存储 关闭资源 package com.lgl.hel

Java之十五 JDBC编程

有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事.换言之,有了JDBCAPI,就不必为访问Sybase数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问Informix数据库又编写另一个程序等等,程序员只需用JDBCAPI写一个程序就够了,它可向相应数据库发送SQL调用.同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java语言"编写一次,处处运行"的优势. Java数