JavaWeb 后端 <十一> 之 DBUtils 框架 (基本使用 结果集 事务处理 对表读取)

一、数据库操作框架

1、ORM:Object Relation Mapping

  Hibernate:非常流行

  JPA:Java Persistent API.ORM标准

  MyBatis:2010年开始。之前叫做iBatis(重视)

2、JDBC封装框架

  DBUtils

  Spring JDBC Template

二、Apache的DBUtils框架(会用:练习作业)

1、基本的使用

DBCPutil

public class DBCPUtil {
	private static DataSource dataSource;
	static{
		try {
			InputStream in = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
			Properties props = new Properties();
			props.load(in);
			dataSource = BasicDataSourceFactory.createDataSource(props);
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static DataSource getDataSource(){
		return dataSource;
	}
	
	public static Connection getConnection(){
		try {
			return dataSource.getConnection();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
}

 dbcpconfig.properties 配置文件 对dbcp进行配置

QueryRunner 的使用  CRUD

/*
create database day18;
use day18;
create table student(
	id int primary key,
	name varchar(100),
	birthday date
);
 */
public class DBUtilCRUD {
	private QueryRunner qr = new QueryRunner(DBCPUtil.getDataSource());
	@Test
	public void testAdd() throws SQLException{
		qr.update("insert into student values(?,?,?)", 1,"杨洋",new Date());
	}
	@Test
	public void testUpdate() throws SQLException{
		qr.update("update student set birthday=? where id=?", "1993-08-01",1);
	}
	@Test
	public void testDel() throws SQLException{
		qr.update("delete from student where id=?", 1);
	}
	//批处理插入10条
	@Test
	public void testBatch() throws SQLException{
		Object params[][] = new Object[10][];//高维:记录的条数。低维:每条记录需要的参数
		for(int i=0;i<params.length;i++){
			params[i] = new Object[]{i+1,"杨洋"+(i+1),new Date()};
		}
		qr.batch("insert into student values(?,?,?)", params);
	}
	//大文本:了解
	/*
	create table t1(
		id int primary key,
		content longtext
	);
	 */
	@Test//大文本类型===Clob
	public void testClob()throws Exception{
		File file = new File("src/pqy&sx.txt");//文件很大,内存浪费
		Reader reader = new FileReader(file);
		char ch[] = new char[(int)file.length()];
		reader.read(ch);
		reader.close();
		Clob clob = new SerialClob(ch);
		qr.update("insert into t1 values(?,?)", 1,clob);//类型不批配。流不是数据库的类型
	}
	//大二进制:了解
	/*
	create table t2(
		id int primary key,
		content longblob
	);
	 */
	@Test//大二进制类型===Blob
	public void testBlob()throws Exception{
		InputStream in  = new FileInputStream("src/22.jpg");
		byte b[] = new byte[in.available()];
		in.read(b);
		in.close();
		Blob blob = new SerialBlob(b);
		qr.update("insert into t2 values(?,?)", 1,blob);//类型不批配。流不是数据库的类型
	}
}

 

2、各种结果处理器的使用 ResultSetHandler

public class ResultSetHandlerDemo {
	private QueryRunner qr = new QueryRunner(DBCPUtil.getDataSource());
	//ArrayHandler:适合结果只有一条的情况。把第一条记录的每列的值封装到一个Object[]数组中
	@Test
	public void test1() throws Exception{
		Object[] objs = qr.query("select * from student", new ArrayHandler());
		for(Object obj:objs)
			System.out.println(obj);
	}
	//ArrayListHandler:适合结果有多条的情况。把每列的值封装到Object[]数组中,把Object[]放到List中
	@Test
	public void test2() throws Exception{
		List<Object[]> list = qr.query("select * from student", new ArrayListHandler());
		for(Object[] objs:list){
			System.out.println("----------------");
			for(Object obj:objs){
				System.out.println(obj);
			}
		}
	}
	//ColumnListHandler:适合取某列的值。把取到值封装到List中
	@Test
	public void test3() throws Exception{
		List<Object> list = qr.query("select * from student", new ColumnListHandler("name"));
		for(Object obj:list){
			System.out.println(obj);
		}
	}
	//KeyedHandler:查询多条记录。每条记录封装到一个Map中,key:字段名,value:字段值。再把Map作为value放到另外一个Map中,该Map的key为指定的列值作为key。
	@Test
	public void test4() throws Exception{
		Map<Object,Map<String,Object>> bmap = qr.query("select * from student", new KeyedHandler("id"));
		for(Map.Entry<Object,Map<String,Object>> bme:bmap.entrySet()){
			System.out.println("--------------------");
			for(Map.Entry<String, Object> lme:bme.getValue().entrySet()){
				System.out.println(lme.getKey()+"="+lme.getValue());
			}
		}
	}
	//MapHandler:适合一条结果。封装到一个Map中,key:字段名,value:字段值
	@Test
	public void test5() throws Exception{
		Map<String,Object> map = qr.query("select * from student", new MapHandler());
		for(Map.Entry<String, Object> lme:map.entrySet()){
			System.out.println(lme.getKey()+"="+lme.getValue());
		}
	}
	//MapListHandler:适合多条结果。把每条封装到一个Map中,key:字段名,value:字段值,在把Map封装到List中
	@Test
	public void test6() throws Exception{
		List<Map<String,Object>> list = qr.query("select * from student", new MapListHandler());
		for(Map<String,Object> map:list){
			System.out.println("--------------------");
			for(Map.Entry<String, Object> lme:map.entrySet()){
				System.out.println(lme.getKey()+"="+lme.getValue());
			}
		}
	}
	//ScalarHandler:适合取结果只有一行和一列的情况。
	@Test
	public void test7() throws Exception{
		Object obj = qr.query("select count(*) from student", new ScalarHandler(1));
//		System.out.println(obj.getClass().getName());
		Long l = (Long)obj;
		System.out.println(l.intValue());
		System.out.println(obj);
	}
}

 

三、实际开发中事务如何管理(非常好)

对事务的控制

1、写4个版本的代码:AOP

1.0

public interface AccountDao {
	/**
	 * 转账
	 * @param sourceAccountName 转出账户
	 * @param targetAccontName 转入账户
	 * @param money 交易金额
	 */
	void transfer(String sourceAccountName,String targetAccontName,float money);
}

 

/*
create table account(
	id int primary key auto_increment,
	name varchar(40),
	money float
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
 */
public class AccountDaoImpl implements AccountDao {
	
	private QueryRunner qr = new QueryRunner();
	
	public void transfer(String sourceAccountName, String targetAccontName,
			float money) {
		Connection conn = null;
		try {
			conn = DBCPUtil.getConnection();
			conn.setAutoCommit(false);//开启事务
			qr.update(conn,"update account set money=money-? where name=?", money,sourceAccountName);
//			int i=1/0;
			qr.update(conn,"update account set money=money+? where name=?", money,targetAccontName);
		} catch (Exception e) {
			if(conn!=null){
				try {
					conn.rollback();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			e.printStackTrace();
		}finally{
			if(conn!=null){
				try {
					conn.commit();
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		
	}

}

 

public interface BusinessService {
	/**
	 * 转账
	 * @param sourceAccountName 转出账户
	 * @param targetAccontName 转入账户
	 * @param money 交易金额
	 */
	void transfer(String sourceAccountName,String targetAccontName,float money);
}

 

public class BusinessServiceImpl implements BusinessService {
	private AccountDao dao = new AccountDaoImpl();
	public void transfer(String sourceAccountName, String targetAccontName,
			float money) {
		dao.transfer(sourceAccountName, targetAccontName, money);
	}

}

 

public class Client {

	public static void main(String[] args) {
		BusinessService s = new BusinessServiceImpl();
		s.transfer("aaa", "bbb", 100);
	}

}

 2.0

//DAO层:不能牵扯到任何业务有关的逻辑。
//DAO:只负责CRUD
public interface AccountDao {
	/**
	 * 根据户名查询账户
	 * @param accountName
	 * @return
	 */
	Account findByName(String accountName);
	/**
	 * 更新账户
	 * @param account
	 */
	void updateAcount(Account account);
}

 

public class AccountDaoImpl implements AccountDao {
	private QueryRunner qr = new QueryRunner();
	private Connection conn;
	public AccountDaoImpl(Connection conn){
		this.conn  = conn;
	}
	public Account findByName(String accountName) {
		try {
			return qr.query(conn,"select * from account where name=?", new BeanHandler<Account>(Account.class),accountName);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public void updateAcount(Account account) {
		try {
			qr.update(conn,"update account set money=? where id=?", account.getMoney(),account.getId());
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
	

}

 

public class Account {
	private int id;
	private String name;
	private float money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public float getMoney() {
		return money;
	}
	public void setMoney(float money) {
		this.money = money;
	}
	
}

 

public interface BusinessService {
	/**
	 * 转账
	 * @param sourceAccountName 转出账户
	 * @param targetAccontName 转入账户
	 * @param money 交易金额
	 */
	void transfer(String sourceAccountName,String targetAccontName,float money);
}

 

//业务层控制事务
public class BusinessServiceImpl implements BusinessService {
	public void transfer(String sourceAccountName, String targetAccontName,
			float money) {
		Connection conn = null;
		try {
			conn = DBCPUtil.getConnection();
			conn.setAutoCommit(false);
			AccountDao dao = new AccountDaoImpl(conn);
			Account sAccount = dao.findByName(sourceAccountName);
			Account tAccount = dao.findByName(targetAccontName);
			sAccount.setMoney(sAccount.getMoney() - money);
			tAccount.setMoney(tAccount.getMoney() + money);
			dao.updateAcount(sAccount);
			// int i=1/0;
			dao.updateAcount(tAccount);
		} catch (Exception e) {
			if (conn != null) {
				try {
					conn.rollback();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			e.printStackTrace();
		} finally {
			if (conn != null) {
				try {
					conn.commit();
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}

}

 

public class Client {

	public static void main(String[] args) {
		BusinessService s = new BusinessServiceImpl();
		s.transfer("aaa", "bbb", 100);
	}

}

 3.0

//封装了所有与事务有关的方法
public class TransactionManager {
	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
	public static Connection getConnection(){
		Connection conn = tl.get();
		if(conn==null){//从当前线程中获取链接
			conn = DBCPUtil.getConnection();
			tl.set(conn);
		}
		return conn;
	}
	public static void startTransaction(){
		try {
			Connection conn = getConnection();
			conn.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	public static void rollback(){
		try {
			Connection conn = getConnection();
			conn.rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	public static void commit(){
		try {
			Connection conn = getConnection();
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	public static void release(){
		try {
			Connection conn = getConnection();
			conn.close();
			tl.remove();//从当前线程中解绑。  与服务器实现有关:服务器采用线程池。
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

 

//业务层控制事务
public class BusinessServiceImpl implements BusinessService {
	private AccountDao dao = new AccountDaoImpl();
	public void transfer(String sourceAccountName, String targetAccontName,
			float money) {
		try {
			TransactionManager.startTransaction();
			Account sAccount = dao.findByName(sourceAccountName);
			Account tAccount = dao.findByName(targetAccontName);
			sAccount.setMoney(sAccount.getMoney() - money);
			tAccount.setMoney(tAccount.getMoney() + money);
			dao.updateAcount(sAccount);
			 int i=1/0;
			dao.updateAcount(tAccount);
		} catch (Exception e) {
			TransactionManager.rollback();
			e.printStackTrace();
		} finally {
			TransactionManager.commit();
			TransactionManager.release();
		}
	}

}

 

public class AccountDaoImpl implements AccountDao {
	private QueryRunner qr = new QueryRunner();
	
	public Account findByName(String accountName) {
		try {
			return qr.query(TransactionManager.getConnection(),"select * from account where name=?", new BeanHandler<Account>(Account.class),accountName);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public void updateAcount(Account account) {
		try {
			qr.update(TransactionManager.getConnection(),"update account set money=? where id=?", account.getMoney(),account.getId());
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
	

}

 4.0  AOP(面向切面编程)

//AOP
public class BeanFactory {
	public static BusinessService getBusinessService(){
		final BusinessService s = new BusinessServiceImpl();
		
		BusinessService proxyS = (BusinessService)Proxy.newProxyInstance(s.getClass().getClassLoader(), 
				s.getClass().getInterfaces(), 
				new InvocationHandler() {
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						try {
							TransactionManager.startTransaction();
							Object rtValue = method.invoke(s, args);
							return rtValue;
						} catch (Exception e) {
							TransactionManager.rollback();
							throw new RuntimeException(e);
						} finally {
							TransactionManager.commit();
							TransactionManager.release();
						}
					}
				});
		
		return proxyS;
	}
}

 

 

2、ThreadLocal(很重要)

//特点:一个线程存的东西,只有该线程才能取出来。线程局部变量。

//模拟

public class ThreadLocal{

//类似Map的结构

private Map<Runnable,Object> map = new HashMap<Runnable,Object>();

public void set(Object obj){

map.put(Thread.currentThread(),obj);

}

public void remove(){

map.remove(Thread.currentThread());

}

public Object get(){

map.get(Thread.currentThread());

}

}

四、利用DBUtils框架进行多表的读取

1、一对多

2、多对多

3、一对一

 

你可能感兴趣的:(JavaWeb 后端 <十一> 之 DBUtils 框架 (基本使用 结果集 事务处理 对表读取))