1. 이름, 아이디, 비밀번호 3가지를 가지는 정보를
DB(여기서는 oracle)에 입력하고 조회하는 기능을
가진 프로그램을 개발하고자 한다. (일단 기능부터)
이를 위해서 다음과 같은 작업을 진행한다.
1). 자바 프로젝트를 생성하고 다음과 같이 작성한다.
우선 가져다 쓸수 있는 User라는 type (class) 하나를 만듬
User.java
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
|
package springbook.user.domain;
public class User {
private String id;
private String name;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
|
2) @. oracle 서버를 이용할 수 있다는 가정하에
다음 oracle 서버에서 테이블 하나를 생성한다.
1
2
3
4
5
6
|
CREATE TABLE users
(
id VARCHAR2(20) PRIMARY KEY,
NAME VARCHAR2(20) NOT NULL,
PASSWORD VARCHAR2(20) NOT null
);
|
3). 다음과 작은 java 파일을 작성한다.
이때 라리브러리로 Oracle을 엑세스 할수 있는 jdbc 파일을 추가한다.
UserDao.java
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import springbook.user.domain.User;
public class UserDao {
//Data Add
public void add(User user) throws ClassNotFoundException , SQLException {
//Class.forName("oracle.jdbc.driver.OracleDriver");
//Connection c =
// DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
Connection c = getConnection();
PreparedStatement ps = c.prepareStatement("insert into users(id,name,password)
values(?,?,?)");
ps.setString(1, user.getId());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
ps.executeUpdate();
ps.close();
c.close();
}
//Data Get
public User get(String id) throws ClassNotFoundException , SQLException {
//Class.forName("oracle.jdbc.driver.OracleDriver");
//Connection c =
// DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
Connection c = getConnection();
PreparedStatement ps = c.prepareStatement("select * from users where id =?");
ps.setString(1, id);
ResultSet rs = ps.executeQuery();
rs.next();
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
return user;
}
//DB연결 중복 (만약에 변경 ... Oracle -> MySql )
private Connection getConnection() throws ClassNotFoundException,SQLException{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection c =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
return c;
}
public static void main(String[] args) throws ClassNotFoundException ,SQLException{
UserDao dao = new UserDao();
User user = new User();
user.setId("kglim");
user.setName("홍길동");
user.setPassword("1004");
//insert
dao.add(user);
System.out.println(user.getId() + "등록성공");
User user2 = dao.get(user.getId());
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user.getId() + "조회성공");
}
}
|
설명 : 보면 알겠지만 간단한 Type 으로 쓸 클래스 하나와 이를 이용해
DB에서 하나의 데이터 type을 저장하고 불러와 콘솔에
뿌려주는 예제임
UserDao 라는 클래스 밑의 get 과 add 메서드에서
드라이버 로딩을 했다가 중복된 내용이 있어서
다른데로 뺀 내용을 볼 수 있다.(중복되니깐)
--> 이 주석처리 하기 전, 후 같은 동작을 보여주지만
코드 소스 내용은 틀리다. ===> 리팩토링
이후엔 드라이버가 바뀌면 getConnection() 만 수정하면 된다.
2. 여기에서 소스 공개는 하지 않고 oracle, Mysql 등을
지원하는 걸 만들고 싶은데 라는 전제하에
상속을 통해서 이를 구현해보고자 한다.
여기서는 수정사항만 기재함
1)우선 UserDao.java 의 getConnection() 메서드를 추상화 시킴
UserDao.java
1
2
3
4
5
6
|
private Connection getConnection() throws ClassNotFoundException,SQLException{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection c =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
return c;
}
|
기존 위 소스 내용을
를 아래와 같이 변경함
1 |
abstract protected Connection getConnection() throws ClassNotFoundException,SQLException;
|
2) 그리고 추상화한 UserDao을 상속받는 DUserDao클래스 를 생성하고
추상화된 메서드 getConnection()을 작성함
DUserDao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DUserDao extends UserDao{
@Override
protected Connection getConnection() throws ClassNotFoundException,
SQLException {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection c =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
return c;
}
}
|
3) 그리고 추상화한 UserDao을 상속받는 NUserDao클래스 를
생성하고 추상화된 메서드 getConnection()을 작성함
NUserDao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class NUserDao extends UserDao{
@Override
protected Connection getConnection() throws ClassNotFoundException,
SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection c =
DriverManager.getConnection("jdbc:mysql://localhost/SpringDB","hr","1004");
return c;
}
}
|
4) 그리고 이렇게 고친 내용이 메인에 반영되도록 메인 함수
일부를 변경(파랑 지움, 빨강 추가)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public static void main(String[] args) throws ClassNotFoundException ,SQLException{
// UserDao dao = new UserDao(); //애는 추상화 클래스니깐 더이상 안씀
UserDao dao = new DUserDao(); //이거나 밑에줄이나 둘중 하나를 사용하면됨
// UserDao dao = new NUserDao();
User user = new User();
user.setId("kglim");
user.setName("홍길동");
user.setPassword("1004");
//insert
dao.add(user);
System.out.println(user.getId() + "등록성공");
User user2 = dao.get(user.getId());
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user.getId() + "조회성공");
}
|
설명2: 두가지 드라이버 로드를 구현하기 위해
getConnection() 을 추상화하고 이를 밖으로 빼서
두개 파일로 드라이버 로드만을 위한 클래스를 만들어서
해당 일을 맡기면
메인에서 불러올때 어느 클래스를 가져오느냐에 따라
다른일을 맡길 수 있음
--- 이런 방식을 템플릿 메서드 패턴이라고 한다.
UserDao 클래스에서 기본로직(추상화 메서드)를 만들고
이를 상속받은 다른 클래스에서 대항 메서드를 구체화 하는 방식임
근데 !!!!! 해보니간 메인 함수에서 필요로한 드라이버에 따라 생성자가
틀려지기 때문에 호출하는 시점에서 변경이 이루어지면
소스 수정이 이루어지기 때문에 이를 좀더 변경해보려고 한다.
3. 다른 방법이 없을까 하다가 DB 연결을 담당하는 메서드를
클래스로 빼볼려고 한다.
SimpleConnectionMaker.java
1
2
3
4
5
6
7
8
9
10
11
12
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SimpleConnectionMaker {
public Connection getConnection() throws ClassNotFoundException , SQLException{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection c =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
return c;
}
}
|
바로 컨넥션 부분을 합쳐버림, 기존에 작성한 두개의 클래스
DUserDao.java, NUserDao.java 는 삭제한다.
메인에 에러가 뜰텐데 그부분에서 다음 을 수정
UserDao 생성자를 추가하는데 생성자에 컨넥트메이커 클래스를 포함시킴
1
2
3
|
public UserDao(){//생성자에 컨넥트 클래스를 가져감
this.simpleConnectionMaker = new SimpleConnectionMaker();
}
|
add, get 함수에 컨넥션 생성시 다음과 같은 방식으로 생성함
Connection c = getConnection();
위 구문을 아래와 같이 변경
Connection c = simpleConnectionMaker.getConnection();
그리고 메인 함수에서는 기존에 바꿨던 UserDao() 생성자를 기존걸로 변경
UserDao dao = new DUserDao();
이런 내용을 아래처럼 생성하는 객체를 아래처럼 인터페이스로 생성함
UserDao dao = new UserDao();
설명 : 2번에서 생성자에 D, N 을 붙여서 생성해야 하는걸 그냥
UserDao()로 쓰고
상황에 따라 D 나 N이 선택되도록 하려고
생성자를 따로 클래스를 만들어서 빼봤다
좋긴 한데 만약 다른 DB 드라이버를 로드하려면
생각처럼 쉽게 안된다.
어쨋든 simpleConnectionMake 클래스에 변경이
이루어지거나 다른 이름의 함수를 만들어서 변경 적용해야 하니간
변경을 다른 데에서 할뿐 음....
그래서 이점을 보완할 방법을 모색해 본다.
4. 인터페이스 클래스 ConnectionMaker.java 를 만들고,
여기안에 있던 내용을 해당 클래스를 상속받는
N, DConnectionMaker.java 두개 파일에 내용을 넣어서
인터페이스 를 구현해서 불러다 써보기를 시도한다.
1) SimpleConnectionMaker.java 를 ConnectionMaker.java 로
변경 및 내용를 인터페이스 화 진행
1
2
3
4
5
6
7
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.SQLException;
public interface ConnectionMaker {
public abstract Connection makeConnection() throws ClassNotFoundException,
SQLException;
}
|
2) ConnectionMaker.java 를 상속받는 두 파일을 아래와같이 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DConnectionMaker implements ConnectionMaker{
@Override
public Connection makeConnection() throws ClassNotFoundException,
SQLException {
// TODO Auto-generated method stub
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection c =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","hr","1004");
return c;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package springbook.user.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class NConnectionMaker implements ConnectionMaker{
@Override
public Connection makeConnection() throws ClassNotFoundException,
SQLException {
// TODO Auto-generated method stub
Class.forName("com.mysql.jdbc.Driver");
Connection c =
DriverManager.getConnection("jdbc:mysql://localhost/SpringDB","hr","1004");
return c;
}
}
|
3) UserDao.java에서 다음과 같이 수정함
우선 클래스 변수 와 생성자 수정
1
2
3
4
|
private ConnectionMaker connectionMaker;
public UserDao(ConnectionMaker SimpleConnectionMaker ){
this.connectionMaker = SimpleConnectionMaker;
}
|
ad, get 함수에서 connection 생성시 다음과 같은 방식으로 대체
Connection c = this.connectionMaker.makeConnection();
메인은 따로 떼어서 UserDaoMain.java라는 클래스를 만들어서 여기에다가 넣어버림
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package springbook.user.dao;
import java.sql.SQLException;
import springbook.user.domain.User;
public class UserDaoMain {
public static void main(String[] args) throws ClassNotFoundException ,SQLException{
UserDao dao = new UserDaoFactory().userDao();
User user = new User();
user.setId("kglim");
user.setName("홍길동");
user.setPassword("1004");
//insert
dao.add(user);
System.out.println(user.getId() + "등록성공");
User user2 = dao.get(user.getId());
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user.getId() + "조회성공");
}
}
|
여기서 빨간줄 친 부분 UserDaoFactory() 을 새로 클래스 만들어서 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package springbook.user.dao;
public class UserDaoFactory {
public UserDao userDao(){
UserDao dao = new UserDao(connectionMaker());
return dao;
}
public ConnectionMaker connectionMaker(){
//여기서 변경 (각 회사의 연결 정보)
ConnectionMaker connectionMaker = new DConnectionMaker();
// ConnectionMaker connectionMaker = new NConnectionMaker();
return connectionMaker;
}
}
|
설명 : 메인을 따로 빼고 기존에 메인 부분에 대한 수정을 없애기 위해서
드라이버 로드 부분을 인터페이스로 구현하고 그 밑에
이를 참조하는 클래스로
구체적인 구현을 진행함
이래도 메인에서는 D를 하느냐 N을 하느냐 하는 구문에 대한 수정이
발생할 수 있기 때문에
이 부분도 아예 따로 빼서 UserDaoFactory() 라는
클래스로 구현함.
그래서 이후에는 UserDaoFactory.java 의 내용만 수정하면
메인에서 수정없이
드라이버를 oracle 또는 mysql 로 변경할수 있게 된다.
댓글 없음:
댓글 쓰기