
DataSource 객체를 스프링 컨테이너에게 제공받아 사용하는 방법
- DataSource 객체는 다수의 Connection 객체를 미리 생성하여 저장하고 있는 객체이다. DBCP(DataBase Connection Pool)이라고 한다.
- Spirng Bean Configuration File에서 DataSource 인터페이스를 상속받은 자식클래스를 Spring Bean으로 등록하여 스프링 컨테이너에게 제공받아 사용할 수 있다.
- DataSource 인터페이스를 상속받은 자식클래스는 Spring 프레임워크에서 제공해주는 spring-jdbc 라이브러리를 빌드 처리하면 된다. (메이븐 사용 : pom.xml)
- DataSource 관련 라이브러리 외에 Oracle Driver 관련 라이브러리도 프로젝트에 빌드 처리해야 한다.
spring-jdbc 라이브러리를 빌드 처리 해주자.
https://mvnrepository.com/artifact/org.springframework/spring-jdbc/6.0.11

오라클 드라이버도 빌드 처리 해준다.
https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc11/23.2.0.0

pom.xml

DataSource 인터페이스를 상속받은 자식 클래스를 Spring Bean으로 등록해주자
- spring-jdbc 라이브러리의 DriverManagerDataSource 클래스를 사용한다.
- DBCP(DataBase Connection Pool) 기능을 제공하는 DataSource 객체를 생성한다.
- DataSource 객체 필드에 Connection 객체를 생성하기 위한 값을 전달하여 저장한다. (Setter Injection)
08_dao.xml

DataSourceApp
public class DataSourceApp {
public static void main(String[] args) throws SQLException {
ApplicationContext context=new ClassPathXmlApplicationContext("08_dao.xml");
DataSource dataSource=context.getBean("dataSource", DataSource.class);
System.out.println("==========================================================");
System.out.println("dataSource = "+dataSource);
Connection connection=dataSource.getConnection();
System.out.println("connection = "+connection);
connection.close();
System.out.println("==========================================================");
((ClassPathXmlApplicationContext)context).close();
}
}

DTO 클래스 및 DAO 클래스가 상속받을 인터페이스 선언
//학생정보를 저장하기 위한 DTO 클래스
@Data
public class Student {
private int no;
private String name;
private String phone;
private String address;
private String birthday;
}
//StudentDAOImpl 클래스(DAO 클래스)가 상속받을 인터페이스
public interface StudentDAO {
int insertStudent(Student student);
int updateStudent(Student student);
int deleteStudent(int no);
Student selectStudent(int no);
List<Student> selectStudentList();
}
SpringDAO 기능을 이용하여 DAO 클래스를 작성할 것이다.
이를 위해선 spring-jdbc 라이브러리가 반드시 프로젝트에 빌드 처리 되어 있어야 한다. (위의 과정에서 이미 빌드 처리 했기 때문에 생략하겠다.)
JdbcTemplate 객체의 메소드를 호출하여 DAO 클래스의 메소드를 작성해주면 된다.
* JdbcTemplate 객체의 메소드 정리
JdbcTemplate.update(String sql, Object ... args)
- SQL 명령(INSERT, UPDATE, DELETE)을 DBMS 서버에 전달하여 실행하는 메소드이며, 조작행의 갯수(int)를 반환한다.
- 매개변수에는 DBMS 서버에 전달하여 실행할 SQL 명령과 InParameter(?) 대신 사용될 값을 차례대로 나열하여 제공하면 된다.
- SQL 명령의 InParameter(?) 갯수만큼 args 매개변수에 값을 반드시 전달해야 한다.
JdbcTemplate.queryForObjcet(String sql, RowMapper<T> rowMapper, Object ... args)
- SQL 명령(SELECT)을 DBMS 서버에 전달하여 실행하는 메소드
- 단일행의 검색결과를 하나의 Java 객체로 반환하기 위해 사용한다.
- 매개변수에는 DBMS 서버에 전달하여 실행할 SQL 명령과 검색행을 Java 객체로 변환하기 위한 매핑정보를 제공하는 RowMapper 객체와 InParameter(?) 대신 사용될 값을 차례대로 나열하여 제공하면 된다.
- RowMapper 객체
- RowMapper 객체는 검색행을 Java 객체로 변환하여 제공하기 위한 매핑정보가 저장된 객체이다.
- 검색행의 컬럼값을 Java 객체 필드에 저장하기 위한 매핑정보를 제공한다.
- RowMapper 인터페이스를 상속받는 자식클래스로 객체를 생성해주면 된다. - 익명의 내부클래스로 객체 생성
- RowMapper 객체를 생성할 때 사용되는 제네릭에는 검색행을 변환할 Java 객체의 자료형을 설정하면 된다.
- RowMapper 인터페이스를 상속받는 자식클래스는 mapRow() 추상 메소드를 오버라이드 선언해주어야 한다.
- mapRow() 메소드의 매개변수로 ResultSet 객체를 제공받아 Java 객체로 변환하는 명령을 작성해주면 된다.
- RowMapper 객체
JdbcTemplate.query(String sql, RowMapper<T> rowMapper, Object ... args)
- SQL 명령(SELECT)을 DBMS 서버에 전달하여 실행하는 메소드
- 다수행의 검색결과를 List 객체로 반환하기 위해 사용한다. - 하나의 검색행은 List 객체의 요소로 저장된다.
- 매개변수에는 DBMS 서버에 전달하여 실행할 SQL 명령과 검색행을 Java 객체로 변환하기 위한 매핑정보를 제공하는 RowMapper 객체와 InParameter(?) 대신 사용될 값을 차례대로 나열하여 제공하면 된다.
StudentDAOImpl (DAO 클래스)
//SpringDAO 기능을 이용하여 DAO 클래스 작성
public class StudentDAOImpl implements StudentDAO {
//JdbcTemplate 객체를 저장하기 위한 필드 선언 - DI 기능을 이용하여 JdbcTemplate를 필드에 저장
// => Spring Bean Configuration File에서 DAO 클래스를 Spring Bean으로 등록할 때 JdbcTemplate 클래스의
//Spring Bean를 제공받아 의존성을 주입한다. (Setter Injection)
@Setter
private JdbcTemplate jdbcTemplate;
//학생정보를 전달받아 STUDENT 테이블에 학생정보를 삽입하고 삽입행의 갯수를 반환하는 메소드
@Override
public int insertStudent(Student student) {
String sql="insert into student values(?,?,?,?,?)";
return jdbcTemplate.update(sql, student.getNo(), student.getName()
, student.getPhone(), student.getAddress(), student.getBirthday());
}
//학생정보를 전달받아 STUDENT 테이블에 저장된 학생정보를 변경하고 변경행의 갯수를 반환하는 메소드
@Override
public int updateStudent(Student student) {
String sql="update student set name=?, phone=?, address=?, birthday=? where no=?";
return jdbcTemplate.update(sql,student.getName(), student.getPhone()
, student.getAddress(), student.getBirthday(), student.getNo());
}
//학생번호를 전달받아 STUDENT 테이블에 저장된 학생정보를 삭제하고 삭제행의 갯수를 반환하는 메소드
@Override
public int deleteStudent(int no) {
return jdbcTemplate.update("delete from student where no=?", no);
}
//학생번호를 전달받아 STUDENT 테이블에 저장된 학생정보를 검색하여 DTO 객체로 반환하는 메소드
@Override
public Student selectStudent(int no) {
try {
String sql="select no, name, phone, address, birthday from student where no=?";
/*
return jdbcTemplate.queryForObject(sql, new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
Student student=new Student();
student.setNo(rs.getInt("no"));
student.setName(rs.getString("name"));
student.setPhone(rs.getString("phone"));
student.setAddress(rs.getString("address"));
student.setBirthday(rs.getString("birthday"));
return student;
}
}, no);
*/
return jdbcTemplate.queryForObject(sql, new StudentRowMapper(), no);
//queryForObject() 메소드로 전달된 SELECT 명령에 대한 검색행이 없는 경우 발생되는 예외
//(queryForObject() 메소드에서만 발생되는 예외)
} catch (EmptyResultDataAccessException e) {
return null;
}
}
//STUDENT 테이블에 저장된 모든 학생정보를 검색하여 List 객체로 반환하는 메소드
@Override
public List<Student> selectStudentList() {
String sql="select no, name, phone, address, birthday from student order by no";
/*
return jdbcTemplate.query(sql, new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
Student student=new Student();
student.setNo(rs.getInt("no"));
student.setName(rs.getString("name"));
student.setPhone(rs.getString("phone"));
student.setAddress(rs.getString("address"));
student.setBirthday(rs.getString("birthday"));
return student;
}
});
*/
return jdbcTemplate.query(sql, new StudentRowMapper());
}
//RowMapper 객체를 생성하기 위해 내부 클래스 선언
public class StudentRowMapper implements RowMapper<Student> {
@Override
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
Student student=new Student();
student.setNo(rs.getInt("no"));
student.setName(rs.getString("name"));
student.setPhone(rs.getString("phone"));
student.setAddress(rs.getString("address"));
student.setBirthday(rs.getString("birthday"));
return student;
}
}
}
Service 클래스를 만들어보자
그전에 Service 클래스가 상속받을 인터페이스를 먼저 선언해주자
StudentService / StudentServiceImpl
//Service 클래스가 상속받을 인터페이스
public interface StudentService {
void addStudent(Student student);
void modifyStudent(Student student);
void removeStudent(int no);
Student getStudent(int no);
List<Student> getStudentList();
}
public class StudentServiceImpl implements StudentService {
//Student 인터페이스를 상속받은 자식클래스의 객체를 저장하기 위한 필드
// => Spring Bean Configuration File에서 Service 클래스를 Spring Bean으로 등록할 때 StudentDAO
//인터페이스를 상속받은 자식클래스의 Spring Bean를 제공받아 의존성을 주입한다. (Setter Injection)
@Setter
private StudentDAO studentDAO;
@Override
public void addStudent(Student student) {
studentDAO.updateStudent(student);
}
@Override
public void modifyStudent(Student student) {
studentDAO.updateStudent(student);
}
@Override
public void removeStudent(int no) {
studentDAO.deleteStudent(no);
}
@Override
public Student getStudent(int no) {
return studentDAO.selectStudent(no);
}
@Override
public List<Student> getStudentList() {
return studentDAO.selectStudentList();
}
}
08_dao.xml
...
<!-- JdbcTemplate 클래스를 Spring Bean으로 등록 -->
<!-- => JdbcTemplate 클래스의 dataSource 필드에 DataSource 인터페이스를 상속받은 자식클래스의
Spring Bean(객체)를 제공받아 의존성 주입(DI) - Setter Injection -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- StudentDAO 인터페이스를 상속받은 자식클래스(StudentDAOImpl 클래스)을 Spring Bean으로 등록 -->
<!-- => StudentDAOImpl 클래스의 jdbcTemplate 필드에 JdbcTemplate 클래스의 Spring Bean(객체)를
제공받아 의존성 주입(DI) - Setter Injection -->
<bean class="xyz.itwill08.dao.StudentDAOImpl" id="studentDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- StudentService 인터페이스를 상속받은 자식클래스(StudentServiceImpl 클래스)을 Spring Bean으로 등록 -->
<!-- => StudentServiceImpl 클래스의 studentDAO 필드에 StudentDAO 인터페이스를 상속받은
자식클래스의 Spring Bean(객체)를 제공받아 의존성 주입(DI) - Setter Injection -->
<bean class="xyz.itwill08.dao.StudentServiceImpl" id="studentService">
<property name="studentDAO" ref="studentDAO"/>
</bean>
...
StudentApp
public class StudentApp {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("08_dao.xml");
StudentService service=context.getBean("studentService", StudentService.class);
System.out.println("==========================================================");
/*
Student newStudent=new Student();
newStudent.setNo(6000);
newStudent.setName("홍경래");
newStudent.setPhone("010-3189-9622");
newStudent.setAddress("서울시 도봉구");
newStudent.setBirthday("1999-05-05");
service.addStudent(newStudent);
*/
/*
Student searchStudent=service.getStudent(6000);
System.out.println(searchStudent);//toString() 메소드를 호출하여 필드값을 반환받아 출력
searchStudent.setName("로빈훗");
searchStudent.setBirthday("1999-02-05");
service.modifyStudent(searchStudent);
*/
service.removeStudent(6000);
List<Student> studentList=service.getStudentList();
for(Student student : studentList) {
System.out.println("학번 = "+student.getNo()+", 이름 = "+student.getName()
+", 전화번호 = "+student.getPhone()+", 주소 = "+student.getAddress()
+", 생년월일 = "+student.getBirthday().substring(0, 10));
}
System.out.println("==========================================================");
((ClassPathXmlApplicationContext)context).close();
}
}
'학원 > 복기' 카테고리의 다른 글
[Spring] MVC2 예제 (Spring) (0) | 2023.08.06 |
---|---|
[Spring] MVC2 예제 (Spring X) (0) | 2023.08.06 |
[Spring] AOP 어노테이션 (0) | 2023.08.06 |
[Spring] AOP 사용 예제 (JavaMail 기능 구현 / StopWatch 객체) (0) | 2023.08.06 |
[Spring] AOP(Aspect Oriented Programming) (0) | 2023.08.03 |