1、ORM:Object Relation Mapping
Hibernate:非常流行
JPA:Java Persistent API.ORM标准
MyBatis:2010年开始。之前叫做iBatis(重视)
2、JDBC封装框架
DBUtils
Spring JDBC Template
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());
}
}
1、一对多
2、多对多
3、一对一