Oracle培训(三十四)——JDBC第七章知识点总结——JDBC高级应用--DAO封装

Oracle培训(三十四)——JDBC第七章知识点总结——JDBC高级应用--DAO封装

知识点预览

JDBC知识回顾

DAO封装

ThreadLocal

JDBC及DAO综合运用


JDBC回顾

1.JDBC

2.ODBC与JDBC

3.JDBC的四种驱动类型

JDBC-ODBC桥加ODBC驱动

本地API驱动

网络协议驱动

本地协议驱动

4.Connection,Statement,ResultSet

5.事务,并发控制

6.行集

7.连接池

8.对象关系映射

9.应用程序架构

三层(多层):显示层,业务逻辑层,数据层

数据访问代码属于业务逻辑层

业务逻辑通过操作数据实现相关功能


DAO封装

1.DAO

Data Access Object—数据访问对象

访问数据库,操作数据的代码

建立数据库连接,操作数据库数据

2.DAO封装

将数据访问代码封装为一个组件,与业务逻辑代码隔开

使数据访问与业务逻辑分离,业务逻辑不需要关心数据操作

应用程序结构清晰,易于维护和扩展,方便的改变数据库及配置

是访问数据的相关技术的综合运用

JDBCConnection,Statement ,ResultSet

事务,并发控制,连接池,行集,ThreadLocal

对象关系映射,多层架构


ThreadLocal


1.问题

多线程访问数据时,每个线程在多个地方要用到连接,难以管理

每个线程打开多个连接对象,浪费资源

2.ThreadLocal

java.lang.ThreadLocal

为解决多线程程序的并发问题提供了一种新的思路

当使用ThreadLocal维护对象时,ThreadLocal为每个使用该对象的线程提供独立的对象副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

使用ThreadLocal管理每个线程使用的连接对象

唯一性:ThreadLocal存储的对象与线程一对一绑定,线程之间不受干扰

持久性:只要没有删除,TreadLocal中存储的对象一直存在,线程可以随时访问

3.ThreadLocal使用

a)ThreadLocal

set(Object obj);//将相关对象存入ThreadLocal中

get(); //从ThreadLocal中取出与当前线程相关的对象

remove(); //从ThreadLocal中删除与当前线程相关的对象

b)与线程相关

4.ThreadLocal示例

TestJDBC1.java

package com.chapter7;

import java.util.Random;

/*
 * ThreadLacal的使用
 */
public class TestJDBC1 implements Runnable{
	//创建线程局部变量personLocal,用来保存Person对象
    private final static ThreadLocal personLocal = new ThreadLocal();
 
    public static void main(String[] agrs) {
    	TestJDBC1 tj = new TestJDBC1();
    	
        Thread t1 = new Thread(tj,"a");
        Thread t2 = new Thread(tj,"b");
        t1.start();
        t2.start();
    }
    public void run(){
    	//获取当前线程的名字
        String currentThreadName = Thread.currentThread().getName();
        System.out.println("线程'"+currentThreadName + "'正在运行!");
        //产生一个随机数并打印
        Random random = new Random();
        int age = random.nextInt(100);
        System.out.println("线程'" + currentThreadName + "'设置年龄:" + age);
        //从ThreadLocal对象中获取一个Person对象,并将随机数年龄插入到对象属性中
        Person person = personLocal.get();
        //线程首次执行此方法的时候,personLocal.get()肯定为null
        if (person == null) {
            //创建一个Person对象,并保存到本地线程变量personLocal中
        	person = new Person();
        	person.setAge(age);
        	personLocal.set(person);
        }
        System.out.println("线程'" + currentThreadName + "'第一次读年龄:" + personLocal.get().getAge());
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        System.out.println("线程'" + currentThreadName + "'第二次读年龄:" + personLocal.get().getAge());
    }
}

Person.java

package com.chapter7;

/*
 * 测试ThreadLocal
 */
public class Person {
	private int age = 0;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}



JDBC及DAO综合运用


1.银行业务模拟系统需求说明

a)银行业务模拟系统需求

模拟银行日常业务

开户、存款,取款,转账

b)DAO封装

将数据访问代码进行封装

与业务代码实现隔离

重点是DAO实现,模拟业务功能

2.银行业务模拟系统

a)显示层

BankTest.java

b)业务逻辑层

BankBiz.java, BankBizImpl.java

BankAccount.java, BankStatement.java

BankAccountDao.java,BankAccountDaoImpl.java

ConnectionFactory.java, jdbc.properties

c)数据层

MySQL

test数据库

bankaccount表,bankstatement表

d)业务逻辑层

BankBiz.java, BankBizImpl.java

进行各种验证,实现开户,存款,取款,转账功能

BankBiz.java是接口,BankBizImpl.ava实现接口,便于扩展

BankAccount.java, BankStatement.java

实体Bean,封装相关表中的数据,在数据库及业务处理代码之间传递数据(集合)

e)BankAccountDao.java,BankAccountDaoImpl.java

操作bankaccount和bankstatement表中的数据

BankAccountDao.java是接口,BankAccountDaoImpl.java实现接口,便于扩展

f)ConnectionFactory.java, jdbc.properties

ConnectionFactory.java读取配置文件,创建连接池并从连接池获得连接

g)DAO相关代码

BankAccount.java, BankStatement.java

实体Bean,封装相关表中的数据,在数据库及业务处理代码之间传递数据(集合)

BankAccountDao.java,BankAccountDaoImpl.java

操作bankaccount和bankstatement表中的数据

BankAccountDao.java是接口,BankAccountDaoImpl.java实现接口,便于扩展

ConnectionFactory.java, jdbc.properties

ConnectionFactory.java读取配置文件,创建连接池并从连接池获得连接

h)连接池,ThreadLocal,事务…

i)业务完成过程


3.银行业务模拟代码分析

a)转账业务(BankTest.java)

Scanner in = new Scanner(System.in);
print("请输入转出账号:");
long fromaccno = in.nextLong();
print("请输入转入账号:");
long toaccno = in.nextLong();
print("请输入转账金额:");
float balance = in.nextFloat();
BankBizImpl bankBiz = new BankBizImpl();
BankAccountDao dao = 
new BankAccountDaoImpl();
bankBiz.setDao(dao);
BankAccount bank = bankBiz.transfer(fromaccno, toaccno, balance);
if(bank!=null){
	println("转账成功,账户信息:");
	println("账户编号:"+bank.getAccno());
	println("账户名称:"+bank.getName());
	println(“账户余额:"+bank.getBalance());
}

b)转账业务(BankBizImpl.java)

public BankAccount transfer(long from, long to, float amt) {
BankAccount  bankfrom = dao.findAccountByAccno(from);
if(bankfrom==null){
System.out.println(
“转出账户不存在,请重新输入!");
return null;
}
//判断余额是否足够
if(bankfrom.getBalance()

c)转账业务(BankAccountDaoImpl.java)

public BankAccount transfer(BankAccount from, BankAccount to, float amt) {
Connection conn = ConnectionFactory.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
BankAccount bank = null;
try {
conn.setAutoCommit(false);
//源账户减少金额
pstmt = conn.prepareStatement("update bankaccount set balance=balance-? where accno=?");
pstmt.setFloat(1,amt);
pstmt.setLong(2,from.getAccno());
pstmt.executeUpdate();
//目标账户增加金额
pstmt = conn.prepareStatement("update bankaccount set balance=balance+? where accno=?");
pstmt.setFloat(1,amt);
pstmt.setLong(2,to.getAccno());
pstmt.executeUpdate();     /以下代码记录转账
pstmt = conn.prepareStatement("insert into bankstatement(action,txdate,amt,fromaccno,toaccno) values(?,?,?,?,?)");
pstmt.setString(1,"转账");
java.util.Date date = new java.util.Date();
pstmt.setDate(2,new Date(date.getTime()));
pstmt.setFloat(3,amt);
pstmt.setLong(4,from.getAccno());
pstmt.setLong(5,to.getAccno());
pstmt.executeUpdate();
//返回账户信息
pstmt = conn.prepareStatement("select * from bankaccount where accno=?");
pstmt.setLong(1,from.getAccno());
rs = pstmt.executeQuery();
bankaccount = new BankAccount();
rs.next();
bankaccount.setAccno(rs.getLong(1));
bankaccount.setName(rs.getString(2));
bankaccount.setBalance(rs.getFloat(3));

conn.commit();
} catch (SQLException se) {
try {    
conn.rollback();    
}
catch (SQLException e) {
throw new RuntimeException(e);
}
throw new RuntimeException(se);
} finally {
try {
if(rs!=null){
 	rs.close();  
}
if(pstmt!=null){  
pstmt.close();  
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
return bankaccount;}

d)转账业务(ConnectionFactory.java)


public class ConnectionFactory {
	private static ThreadLocal connThread = new ThreadLocal();
	private static Properties pros = System.getProperties();
	
	static {
		try {
			InputStream is = ConnectionFactory.class.getResourceAsStream("jdbc.properties");
			pros.load(is);
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	public static Connection getConnection() {
		Connection con = connThread.get();
		if(con == null){
		    try{
		    	DataSource ds = BasicDataSourceFactory.createDataSource(pros);
		    	con = ds.getConnection();
		    	connThread.set(con);
		    }catch(SQLException se){
		    	se.printStackTrace();
		    	throw new RuntimeException(se);
		    } catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return con;
	}
	
	public static void release(){
		Connection con = getConnection();
		if(con != null){
			try{
				con.close();
			}catch(SQLException se){}
		}
		
		connThread.set(null);
	}


e)转账业务(jdbc.properties)

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=gbk
username=root
password=root
maxActive=50
maxIdle=20
maxWait=60000


i.数据库产品:MySQL

ii.数据库名称:test

iii.表:bankaccountbankstatement

f)转账业务完成过程


g)转账业务(运行结果)



开户,存款,取款,列出所有账户信息……

4.DAO总结

a)DAO

实体Bean:将数据库数据封装为对象,在业务逻辑代码、数据访问代码、显示层之间传递

dao:对数据库数据进行添加,修改,删除,查询操作

连接池:提高数据访问效率

b)三层结构

业务逻辑层=业务处理代码+DAO

c)N层结构

显示层--》业务逻辑层--》数据访问层(DAO)--》数据库

d)DAO封装

将数据访问代码封装为一个组件,与业务逻辑代码隔开

使数据访问与业务逻辑分离

应用程序结构清晰,易于维护和扩展

e)实现DAO

JDBC

事务,连接池……

ThreadLocal

三层/N层架构

事务(dao层)--》事务(业务层)

你可能感兴趣的:(Oracle培训(三十四)——JDBC第七章知识点总结——JDBC高级应用--DAO封装)