24. DbUtils 프레임워크의 응용(JavaEE 노트)

16914 단어
아래의 모든 예는 공사day17에 있다.
1. 모의 이체
먼저 데이터베이스를 구축합니다.
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);

주의: 여기는 데이17 데이터베이스를 사용합니다.
솔리드 클래스Account.java
private int id;
private String name;
private float money;

실제 개발에서 JDBC를 사용할 때 하나의 클래스ThreadLocal이 필요합니다. 여기서 우리는 이러한 개선 도구 클래스를 사용합니다: JdbcUtils.java
package cn.itcast.utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JdbcUtils {
    private static ComboPooledDataSource ds = null;
    private static ThreadLocal threadLocal = new ThreadLocal();
    
    static{
        ds = new ComboPooledDataSource();
    }
    
    public static Connection getConnection() throws SQLException{
        Connection connection = threadLocal.get();
        if(connection == null){
            connection = getDataSource().getConnection();//        ,          
            threadLocal.set(connection);
        }
        return connection;
    }
    public static DataSource getDataSource(){
        return ds;
    }
    
    public static void startTransaction(){
        try{
            Connection connection = threadLocal.get();
            if(connection == null){//            ,    ,       
                connection = getConnection();
                threadLocal.set(connection);// connection        
            }
            connection.setAutoCommit(false);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
        
    }
    public static void rollback(){
        try{
            Connection connection = threadLocal.get();
            if(connection != null){
                connection.rollback();
            }
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
    public static void commit(){
        try{
            Connection connection = threadLocal.get();
            if(connection != null){
                connection.commit();
            }
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
    public static void release(){
        try{
            Connection connection = threadLocal.get();
            if(connection != null){
                connection.close();
                threadLocal.remove();//          connection,    
            }
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

설명: ThreadLocal에 대해 우리는 이렇게 이해할 수 있다. 이 종류는 하나의 용기이다.이 용기에 저장된 대상 (저장은 set 방법을 사용합니다) 은 현재 라인 범위 내에서 모두 꺼낼 수 있습니다.다음은 예를 통해 설명합니다Test.java.
package junit.test;
public class Test {

    public static void main(String[] args) {
        
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread);
        
        ThreadLocal t = new ThreadLocal();
        t.set("aaa");  //               map(currentThread,"aaa")
        
        String value = (String) t.get();
        System.out.println(value);
    }
}

설명: 우리는 이 클래스를 도구 클래스를 개선하고 현재의 Connection을 현재 라인에 연결시켜 데이터베이스 조작을 할 때 모든 조작이 같은 Connection을 사용하도록 보장할 수 있다.각 방법에 대해 Connection 작업에 주의하십시오.
dao층: AccountDaoImpl.java
package cn.itcast.dao.impl;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import cn.itcast.dao.AccountDao;
import cn.itcast.domain.Account;
import cn.itcast.utils.JdbcUtils;

public class AccountDaoImpl implements AccountDao {
    
    //            ,      
    private Connection conn = null;
    
    public AccountDaoImpl(Connection conn){
        this.conn = conn;
    }
    
    public AccountDaoImpl(){
        
    }
    
    public void update(Account account) throws SQLException{
        
        QueryRunner qr = new QueryRunner();
        String sql = "update account set name=?,money=? where id=?";
        Object params[] = {account.getName(),account.getMoney(),account.getId()};
        qr.update(JdbcUtils.getConnection(),sql, params);
        
    }
    
    public Account find(int id) throws SQLException{
        QueryRunner qr = new QueryRunner();
        String sql = "select * from account where id=?";
        return (Account) qr.query(JdbcUtils.getConnection(),sql, id, new BeanHandler(Account.class));
    }
}

설명: 연결을 사용할 때 데이터베이스 링크 탱크에 맡길 수 없습니다. 하나의 작업(예를 들어 업데이트)이 끝나면 연결 탱크가 연결을 해제할 수 있기 때문입니다. 따라서QueryRunner류를 사용할 때 링크를 전달하지 마십시오. 이렇게 하면 업데이트를 사용하여 링크를 전달할 때 작업이 끝난 후에 링크를 해제하지 않습니다.이 방법으로 링크를 전달하는 것과 전달하지 않을 때의 차이에 주의하십시오.
비즈니스 클래스: AccountService.java
package cn.itcast.service;
import java.sql.Connection;
import java.sql.SQLException;
import cn.itcast.dao.AccountDao;
import cn.itcast.dao.impl.AccountDaoImpl;
import cn.itcast.domain.Account;
import cn.itcast.utils.JdbcUtils;

public class AccountService {
    
    //                 (     ),      ThreadLocal ,      ,
    //               
    public void transfer(int sourceid, int targetid, float money) throws SQLException{
        
        Connection connection = null;
        try{
            JdbcUtils.startTransaction();//      ,      ,                 
            
            AccountDao dao = new AccountDaoImpl(connection);
            Account source = dao.find(sourceid);
            Account target = dao.find(targetid);
            
            source.setMoney(source.getMoney()-money);
            target.setMoney(target.getMoney()+money);
            
            dao.update(source);//            ,   dao   update          ,       
            dao.update(target);
            
            JdbcUtils.commit();
            
        }catch(Exception e){
            e.printStackTrace();
            JdbcUtils.rollback();
        }finally{
            JdbcUtils.release();
        }   
    }
}

설명: 물론 여기서 우리는 데이터베이스에 대한 조작을 같은 업무에서 완성할 수 있을 뿐이다. 그러나 때때로 우리는 여러 개의 서비스가 같은 업무에서 필요할 수도 있다. 이때 우리는 차단기를 사용해야 한다. 웹이 요청할 때 직접 차단하고 서비스에 연결을 가져온다. 그러면 모든 서비스가 같은 업무에서차단기는 ThreadLocal 관리를 사용합니다.물론 뒤에서 우리는 보통spring을 이용하여 업무를 관리한다.
테스트: AccountServiceTest.java
package junit.test;
import java.sql.SQLException;
import org.junit.Test;
import cn.itcast.service.AccountService;
public class AccountServiceTest {

    @Test
    public void testTransfer() throws SQLException{
        AccountService service = new AccountService();
        service.transfer(1, 2, 100);
    }
}

2. JDBC를 사용하여 여러 테이블을 조작한다(공정day172.1 일대다 관계(부서 및 직원)
관련 항목: Department.java
private String id;
private String name;
private Set employees = new HashSet();
Employee.java
private String id;
private String name;
private double salary;
private Department department;

데이터베이스 테이블을 만들려면 다음과 같이 하십시오.
    create table department
    (
        id varchar(40) primary key,
        name varchar(40)
    );
    
    create table employee
    (
        id varchar(40) primary key,
        name varchar(40),
        salary double,
        department_id varchar(40),
        constraint department_id_FK foreign key(department_id) references department(id)
    );

dao층: DepartmentDaoImpl.java
package cn.itcast.dao.impl;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import cn.itcast.dao.DepartmentDao;
import cn.itcast.domain.Department;
import cn.itcast.domain.Employee;
import cn.itcast.utils.JdbcUtils;

public class DepartmentDaoImpl implements DepartmentDao {
    //session.add(department);
    public void add(Department department) throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        
        //1.  department          department 
        String sql = "insert into department(id,name) values(?,?)";
        Object params[] = {department.getId(),department.getName()};
        qr.update(sql, params);
        
        //2.   department          ,     
        sql = "insert into employee(id,name,salary,department_id) values(?,?,?,?)";
        Set set = department.getEmployees();
        Object params2[][] = new Object[set.size()][];
        
        int index = 0;
        for(Employee e : set){
            params2[index++] = new Object[]{e.getId(),e.getName(),e.getSalary(),department.getId()};
        }
        qr.batch(sql, params2);//     
    }
    
    public Department find(String id) throws SQLException{
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        
        //1.        ,  department   
        String sql = "select * from department where id=?";
        Department d = (Department) qr.query(sql, id, new BeanHandler(Department.class));
        
        /*  :              ,            
            ,                
                             ,        
                   ,       ,         
                ,          */
        
        //2.            ,  department          
        sql = "select id,name,salary from employee where department_id=?";
        List list = (List) qr.query(sql, id, new BeanListHandler(Employee.class));
        
        d.getEmployees().addAll(list);//          set   
        
        return d;
    }
    
}

테스트: DepartmentService.java
package cn.itcast.test;
import java.sql.SQLException;
import java.util.UUID;
import cn.itcast.dao.DepartmentDao;
import cn.itcast.dao.impl.DepartmentDaoImpl;
import cn.itcast.domain.Department;
import cn.itcast.domain.Employee;
public class DepartmentService {
    
    DepartmentDao dao = new DepartmentDaoImpl();
    
    public void add() throws SQLException{
        Department d = new Department();
        d.setId(UUID.randomUUID().toString());
        d.setName("   ");
        
        Employee e1 = new Employee();
        e1.setId(UUID.randomUUID().toString());
        e1.setName("aaa");
        e1.setSalary(300);
        
        Employee e2 = new Employee();
        e2.setId(UUID.randomUUID().toString());
        e2.setName("bbb");
        e2.setSalary(400);
        
        d.getEmployees().add(e1);
        d.getEmployees().add(e2);
        
        dao.add(d);
    }
}

2.2 다대다(선생님과 학생)
관련 실체류: Teacher.java
private String id;
private String name;
private double salary;
private Set students = new HashSet();
Student.java
private String id;
private String name;
private Set teachers = new HashSet();

데이터베이스 테이블을 만들려면 다음과 같이 하십시오.
    create table teacher
    (
        id varchar(40) primary key,
        name varchar(40),
        salary double
    );
    
    create table student
    (
        id varchar(40) primary key,
        name varchar(40)
    );
    
    create table teacher_student
    (
        teacher_id varchar(40),
        student_id varchar(40),
        primary key(teacher_id,student_id),
        constraint teacher_id_FK foreign key(teacher_id) references teacher(id),
        constraint student_id_FK foreign key(student_id) references student(id)
    );

설명: 다대다와 같은 관계에 대해 우리는 일반적으로 실체류 간의 관계를 보존하기 위해 표를 단독으로 세운다.
dao층: TeacherDaoImpl.java
package cn.itcast.dao.impl;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import cn.itcast.dao.TeacherDao;
import cn.itcast.domain.Student;
import cn.itcast.domain.Teacher;
import cn.itcast.utils.JdbcUtils;

public class TeacherDaoImpl implements TeacherDao {

    public void add(Teacher t) throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        
        //1.         ,     
        String sql = "insert into teacher(id,name,salary) values(?,?,?)";
        Object params[] = {t.getId(),t.getName(),t.getSalary()};
        qr.update(sql, params);
        
        ///2.           ,     
        Set set = t.getStudents();
        for(Student s : set){
            sql = "insert into student(id,name) values(?,?)";
            params = new Object[]{s.getId(),s.getName()};
            qr.update(sql, params);
            
            //3.               
            sql = "insert into teacher_student(teacher_id,student_id) values(?,?)";
            params = new Object[]{t.getId(),s.getId()};
            qr.update(sql, params);
        }
    }
    
    public Teacher find(String id) throws SQLException{
    
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        
        //1.              
        String sql = "select * from teacher where id=?";
        Teacher t = (Teacher) qr.query(sql, id, new BeanHandler(Teacher.class));
        
        //2.                  (         ,      ,        ,    ,       ,     )
        sql = "select s.id,s.name from teacher_student ts,student s where teacher_id=? and ts.student_id=s.id";
        List list = (List) qr.query(sql, id, new BeanListHandler(Student.class));
        
        t.getStudents().addAll(list);
        
        return t;
    }
}

테스트: BusinessService.java
@Test
    public void addTeacher() throws SQLException{
        
        Teacher t = new Teacher();
        t.setId("1");
        t.setName("  ");
        t.setSalary(1000000);
        
        Student s1 = new Student();
        s1.setId("1");
        s1.setName("aaa");
        
        Student s2 = new Student();
        s2.setId("2");
        s2.setName("bbb");
        
        t.getStudents().add(s1);
        t.getStudents().add(s2);
        
        tdao.add(t);
    }
    
    @Test
    public void findTeacher() throws SQLException{
        Teacher t = tdao.find("1");
        System.out.println(t);
    }

2.3 일대일(사람과 신분증)
관련 실체류: Person.java
private String id;
private String name;
private Idcard idcard;
IdCard.java
private String id;
private String address;
private Person person;

데이터베이스 테이블을 만들려면 다음과 같이 하십시오.
    create table person
    (
        id varchar(40) primary key,
        name varchar(40)
    );
    
    create table idcard
    (
        id varchar(40) primary key,
        address varchar(100),
        constraint id_FK foreign key(id) references person(id)
    );

설명: 이런 일대일 관계에 대해 우리는 신분증 쪽에서 관계를 유지하는 것을 선택했고 당연히 사람 쪽에서도 관계를 유지할 수 있다.
dao층: PersonDaoImpl.java
package cn.itcast.dao.impl;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import cn.itcast.dao.PersonDao;
import cn.itcast.domain.Person;
import cn.itcast.utils.JdbcUtils;

public class PersonDaoImpl implements PersonDao {

    public void add(Person p) throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        
        //  person     person 
        String sql = "insert into person(id,name) values(?,?)";
        Object params[] = {p.getId(),p.getName()};
        qr.update(sql, params);
        
        
        //              
        sql = "insert into idcard(id,address) values(?,?)";
        params = new Object[]{p.getId(),p.getIdcard().getAddress()};
        qr.update(sql, params);
    }
}

테스트:
    @Test
    public void addPerson() throws SQLException{
        
        Person p = new Person();
        p.setId("1");
        p.setName("aaa");
            
        Idcard idcard = new Idcard();
        idcard.setId("1");
        idcard.setAddress("  ");
        
        p.setIdcard(idcard);
        
        pdao.add(p);
    }

마지막: 이상의 예는 기본적인 원리를 설명했을 뿐 실제 개발의 예로 삼을 수 없다. 모두 비교적 간단하기 때문에 여기서 더 이상 말하지 않겠다.

좋은 웹페이지 즐겨찾기