By
zhpooer
4月 26 2014
更新日期:5月 5 2014
ORM简介
ORM(Object Relation Mapping):
Object : JavaBean对象
Raltion: 关系型数据库
Mapping: 映射(存在在着对应关系)
框架: Hibernate、MyBatis(iBatis)、JPA(java持久化框架, 规范)
简单的JDBC框架: 这些框架只是对JDBC操作的简单封装. 比如DBUtils\SpringJDBCTemplate
DBUtils 框架的使用
Dbutils 是Apache提供的JDBC简单框架
QueryRunner
int[] batch(String sql, Object[][] params)
: 执行批处理
sql: 执行的语句
params: 二维数组,高纬表示执行的语句的条数, 低维表示每条语句的参数
返回每条语句影响到的记录行数
T query(String sql, ResultSetHandler rsh)
适合执行sql查询, 把结果封装到JavaBean中
T query(String sql, ResultSetHandler rsh, Object... params)
int update(String sql)
执行 insert update delete 语句
int update(String sql, Object... params)
int update(String sql, Object param)
Bean封装
1
2
3
4
5
create table user (
id int primary key ,
name varchar (20 ),
birthday date
);
1
2
3
4
5
public class User{
private int id;
private String name;
private Date birthday;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private QueryRunner qr = new QueryRunner(datasource);
public void testAdd (){
qr.update("insert into user values(?, ?, ?)" , 1 , "aaa" , new Date());
}
public void testUpdate (){
qr.update("update user set name=? where id=?" , "aaa" , new Date(), 1 );
}
public void testDel (){
qr.update("delete from user where id=?" , 1 );
}
public void testQueryOne (){
User u = qr.query("select * from user where id=1" , new BeanHandler<User>(User.class), 1 );
}
public void testQuery1 (){
User u = qr.query("select * from user" , new BeanHandler<User>(User.class));
}
public void testMulti (){
List<User> us = qr.query("select * from user" , new ListBeanHandler<User>(User.class));
}
public void testBatch (){
Object params [][] = new Object[10 ][];
for (int i=0 ;i<params .length;i++){
params [i] = new Object[]{i+1 , "aaa" + ()i+1 ), new Date()}
}
qr.batch("insert into user values(?,?,?)" , params );
}
DBUtils 中的结果处理器详解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void testArrayHandler (){
Object objs[] = qr.query("select * from user" , new ArrayHandler());
}
public void testArrayListHandler (){
List<Object[]> list = qr.query("select * from user" , new ArrayListHandler());
}
public void testColumnListHandler (){
List<Object> list = qr.query("select * from user" , new ColumnListHandler("name" ));
}
public void testKeyedHandler (){
Map<Object,Map<String,Object>> bmap = qr.query("select * from user" , new KeyedHandler("id" ));
}
public void testMapHandler (){
Map<String, Object> map = qr.query("select * from user" , new MapHandler());
}
public void testMapListHandler (){
List<Map<String, Object>> list = qr.query("select * from user" , new MapListHandler);
}
public void testScalarHandler (){
Object list = qr.query("select count(*) from user" , new ScalarHandler(1 ));
}
ThreadLocal
ThreadLocal 提供了线程局部变量
分析原理
ThreadLocal 内部有一个Map, Map的Key是当前线程对象, value是一个Objct对象. 模拟 :
1
2
3
4
5
6
7
8
9
10
11
12
public class ThreadLocal<T>{
private Map<Runnable, T> map = new HashMap<Runnable, T>();
public void set (T t){
map.put(Thread.currentThread(), t);
}
public void remove (){
map.remove(Thread.currentThread());
}
public T get (){
return map.get (Thread.currentThread());
}
}
真实案例中的事务控制
QueryRunner(DataSource conn) // 这个每条语句执行,都是不同的连接(Connection), 不能在同一个事务中执行语句
QueryRunner() //因为需要所有语句执行要在同一个事务中执行, 在执行语句时, 要传入(Connection)
DAO层: 只负责数据库的访问, 只有增删改查
事务控制的要求: 一般是业务上的要求, 一个事务就是一个业务, 事务控制 不能在放在DAO
版本一
DAO层
1
2
3
4
5
6
7
public void findAccontByName (acconntname){
Account account = qr.query("select * from account where name=?" , new BeanHandler<Account>(Account.class), accountName);
}
public void updateAccount (Account account){
qr.update("udpate set " , account.id, account.name)
}
业务逻辑
1
2
3
4
5
6
7
8
9
10
11
12
Connection conn = dataSource.getConnection ()
conn.setAutoCommit (false)
dao.setConnection (conn)
Account sourceAccount = dao.findAccontByName (sourceAccountName)
Account targetAccount = dao.findAccontByName (targetAccountName)
sourceAccount.setMoney (any)
targetAccount.setMoney (any)
dao.update (sourceAccount)
dao.update (targetAccount)
conn.setAutoCommit (true)
版本二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class TransactionManager{
private static ThreadLocal<Connection> t1 = new ThreadLocal<Connection>();
public static Connection (){
Connecton conn = t1.get ();
if (conn==null ){
conn = dataSource.getConnection();
t1.set (conn);
}
return conn;
}
public static void startTransaction (){
Connection conn = getConnection();
conn.setAutoCommit(false );
}
public static void commit (){
Connection conn = getConnection();
conn.commit();
}
public static void rollback (){
Connection conn = getConnection();
conn.rollback();
}
public static void release (){
Connection conn = getConnection();
conn.close();
t1.remove();
}
}
业务逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
TransactionManager.startTransaction ()
dao.setConnection (conn)
Account sourceAccount = dao.findAccontByName (sourceAccountName)
Account targetAccount = dao.findAccontByName (targetAccountName)
sourceAccount.setMoney (any)
targetAccount.setMoney (any)
dao.update (sourceAccount)
dao.update (targetAccount)
TransactionManager.commit ()
TransactionManager.rollback ()
TransactionManager.release ()
DAO层
1
2
3
4
5
6
7
public void findAccontByName (acconntname){
Account account = qr.query(TransactionManager.getConnection(), "select * from account where name=?" , new BeanHandler<Account>(Account.class), accountName);
}
public void updateAccount (Account account){
qr.update(transactionmanager.getconnection(), "udpate set " , account.id, account.name)
}
版本三
提取 service 中的关于 Transaction 的重复代码, 使用动态代理
1
2
3
public Interface BusinessService{
public void transform (){}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class BeanFactory {
public static BusinessService getBusinessService (){
BusinessService s = new BusinessService();
BusinessService proxy = Proxy.newProxyInstancee(
getClassLoader(), s.getClass().getInterfaces(),
new InvocationHandler() {
@Override public Object invoke () {
TransactionManager.startTransaction();
Object rtValue = method.invoke(s, args);
TransactionManager.commit();
TransactionManager.rollback();
TransactionManager.release();
return rtValue;
}
});
}
}
多表存取
一对多
一个客户可以有许多订单
模型类
1
2
3
4
5
6
7
8
9
10
11
create table customer(
id int primary key ,
name varchar (100 )
)
create table orders(
id int primary key ,
num varchar (100 ),
money float (8 ,0 ),
customer_id int ,
constraint customer_id_ref foreign key (customer_id) referrence customer(id)
)
1
2
3
4
5
6
7
8
9
10
11
public class Customer {
private int id;
private String name;
private List<Orders> orders = new ArrayList<Orders>
}
public class Orders {
private int id;
private String num;
private float money;
private Customer customer;
}
Dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class CustomerDaoImpl{
private QueryRunner rq;
public void addCustomer (Customer c){
rq.update("" , c.getId(), c.getName());
List<Orders> os = c.getOrders();
if (os!=null &&os.size()>0 ){
for (Orders o:os){
os.update("" , o.getId...);
}
}
}
public Customer findByCustomerId (int id){
Customer c = rq.query("select * from customer where id=?" , new BeanHandler<Customer>(), id);
if (c!=null ){
List<Orders> os = qr.query("select * from orders where customer_id=?" ), new BeanListHander<Orders>, c.getId());
c.setOrders(os);
}
return c;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CustomerDaoTest {
public void testAdd (){
Customer c = new Customer();
c.setId(1 );
c.setName("" );
Orders o1 = new Orders();
o1.setId(1 );
o1.setNum("201401" );
o1.setMoney(1000 );
c.getOrders().add(o1);
Orders o2 = new Orders();
o2.setId(1 );
o2.setNum("201401" );
o2.setMoney(1000 );
c.getOrders().add(o2);
dao.addCustomer(c);
}
public void testQuery (){
Customer c = dao.findByCustomerId(1 );
List<Orders> os = c.getOrders();
}
}
多对多
学生和老师的关系是多对多
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
create table teacher (
id int primary key ,
name varchar (100 ),
salary float (8 ,0 )
);
create table student(
id int primary key ,
name varchar (100 ),
grade varchar (100 )
);
create table teacher_student(
t_id int ,
s_id int ,
primary key (t_id, s_id),
constraint t_id_fk foreign key (t_id) referrences teacher(id),
constraint s_id_fk foreign key (s_id) referrences student(id)
);
1
2
3
4
5
6
7
8
9
10
11
12
public class Teacher {
private int id;
private String name;
private float salary;
private List<Student> studnents = new ArrayList();
}
public class Student{
private int id;
private String name;
private String grade;
private List<Teacher> teachers = new ArrayList();
}
Dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void addTeacher (){
qr.update("insert int teacher values(?,?,?)" , t.getId(), t.getName());
List<Student> sts = t.getStudnets();
if (students!=null && students.size()>0 ){
for (Student s:students){
Student dbs = qr.query("select * from student where id=?" , BeanHandler(), s.getId());
if (dbs==null ){
qr.update("insert into student values(?,?,?)" );
}
qr.update("insert into teacher_student values(?,?)" , t.getId(), s.getId());
}
}
}
public void findTeacherById (int id){
Teacher t = qr.query("select * from teacher where id=?" , BeanHandler, teacher.getId);
if (t!=null ){
String sql = "select s.* from teacher_student inner join student s on s.id=ts.s_id where ts.t_id=?" ;
List<Student> ss = qr.query(sql, new BeanListHander<Student>);
t.setStudents(ss);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void testAddTeacher(){
Teacher t1 = new Teacher()
t1.setId (1 )
t1.setName ("qb" )
t1.setSalary (10 )
Teacher t2 = new Teacher()
t2.setId (1 )
t2.setName ("wzt" )
t2.setSalary (10 )
Student s1 = new Student()
s1.setId (1 )
s1.setName ("hcH" )
s1.setGrade ("A" )
t1.getStudents ().add (s1)
t2.getStudents ().add (s1)
}
public void testQuery(){
Teacher t = dao.findTeacherById (1 )
}
一对一
有主键关联 和外键关联
身份证和公民是一对一
1
2
3
4
5
6
7
8
9
create table person (
id int primary key ,
name varchar (100 )
);
create table idcard (
id int primary key ,
num varchar (100 ),
constraint i_id_fk foreign key (id) references person(id)
);
1
2
3
4
5
6
7
8
9
10
11
public class Person{
private int id;
private String name;
private IdCard idCard;
}
public class IdCard {
private ind id;
private String num;
private Person person;
}
DAO层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void addPerson (Person p){
qr.update("insert into person values(?,?)" );
IdCard idcard = p.getIdCard();
if (idcard!=null ){
qr.update("insert into idcard values(?,?)" )
}
}
public Person findPersonById (int id) {
Person p = qr.query("select * from person where id=?" , new BeanHandler<Person>, id)
if (p!=null ){
IdCard idCard = qr.query("select * from idcard where id=?" , BeanHandler<IdCard),id)
p.setIdCard(idcard);
}
}