티스토리 뷰
파일 구조
ㄴconfig
ㄴApplicationConfig.java
ㄴDBConfig.java
ㄴdao
ㄴRoleDao.java
ㄴdto
ㄴRole.java
ㄴmain
ㄴTest.java
pom.xml 설정 및 DAO 작성
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.1.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- basic data source -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<!-- mariaDB -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
Role.java
public class Role {
private int roleId;
private String description;
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Role [roleId=" + roleId + ", description=" + description + "]";
}
}
ApplicatoinConfig.java
@Configuration
@ComponentScan(basePackages = { "kr.or.connect.daoexam.dao" })
@Import({ DBConfig.class })
public class ApplicationConfig {
}
DBConfig.java
@Configuration
@EnableTransactionManagement
public class DBConfig {
private String driverClassName = "org.mariadb.jdbc.Driver";
private String url = "jdbc:mariadb://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8";
private String username = "connectuser";
private String password = "connect123!@#";
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
JdbcTemplate 클래스를 이용한 RoleDao.java 작성
@Repository
public class RoleDao {
private JdbcTemplate jdbc;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public RoleDao(DataSource dataSource) {
this.jdbc = new JdbcTemplate(dataSource);
}
public int jdbcTest01() {
return this.jdbc.queryForObject("select count(*) from role", Integer.class);
}
public int jdbcTest02(int roleId) {
try {
return this.jdbc.queryForObject("select count(*) from role where role_id = ?", Integer.class, roleId);
} catch (EmptyResultDataAccessException e) {
return 0;
}
}
public String jdbcTest03(int roleId) {
try {
return this.jdbc.queryForObject("select description from role where role_id = ?", new Object[]{roleId}, String.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
public Role jdbcTest04(int roleId) {
try {
return this.jdbc.queryForObject("select * from role where role_id = ?", new Object[]{roleId}, rowMapper);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
public List<Role> jdbcTest05() {
return (List<Role>) this.jdbc.query("select * from role", rowMapper);
}
public int jdbcTest06(int roleId, String description) {
return this.jdbc.update("insert into role values (?, ?)", roleId, description);
}
public int jdbcTest07(int roleId, String description) {
return this.jdbc.update("update role set description = ? where role_id = ?", description, roleId);
}
public int jdbcTest08(int roleId) {
return this.jdbc.update("delete from role where role_id = ?", roleId);
}
}
NamedParameterJdbcTemplate 클래스를 이용한 RoleDao.java 작성
@Repository
public class RoleDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
//스프링4.0 이상부터 @Autowired 없어도 Bean 객체라면 의존성이 주입된다.
public RoleDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource).withTableName("role");
}
public List<Role> selectAll() {
//NamedJdbcTemplate은 Map을 이용해서 값을 바인딩하는데 바인딩할 값이 없기 때문에 emptyMap을 넣어줌
return jdbc.query("SELECT role_id, description FROM role order by role_id", Collections.emptyMap(), rowMapper);
}
public int insert(Role role) {
//role객체를 Map객체로 변환
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return insertAction.execute(params);
}
public int update(Role role) {
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return jdbc.update("UPDATE role SET description = :description WHERE role_id = :roleId", params);
}
public int deleteById(Integer id) {
Map<String, ?> params = Collections.singletonMap("roleId", id);
return jdbc.update("DELETE FROM role WHERE role_id = :roleId", params);
}
public Role selectById(Integer id) {
try {
Map<String, ?> params = Collections.singletonMap("roleId", id);
return jdbc.queryForObject("SELECT role_id, description FROM role WHERE role_id = :roleId", params, rowMapper);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
다건 Select
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
List<Role> list = roleDao.selectAll();
for(Role role : list) {
System.out.println(role);
}
단건 Select
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
Role resultRole = roleDao.selectById(201);
System.out.println(resultRole);
Insert
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
Role role = new Role();
role.setRoleId(201);
role.setDescription("PROGRAMMER");
int count = roleDao.insert(role);
System.out.println(count + "건 입력하였습니다.");
Update
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
Role role = new Role();
role.setRoleId(201);
role.setDescription("PROGRAMMER");
int count = roleDao.update(role);
System.out.println(count + "건 수정하였습니다.");
Delete
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
int deleteCount = roleDao.deleteById(201);
System.out.println(deleteCount + "건 삭제하였습니다.");
사용된 Class와 Method
- SimpleJdbcInsert
- 인스턴스화해서 사용한다.
- 초기화에 DataSource를 인자로 받는다.
- withTableName으로 테이블명을 설정한다.
- execute() 메소드의 파라미터로 java.utils.Map을 받는다.
- 이때 Map에 사용한 키는 데이터베이스에 정의한 테이블의 컬럼명과 일치해야 한다.
- RowMapper
- SQL의 결과(record type)를 객체(object type)에 Mapping하여 리턴한다.
- BeanPropertyRowMapper.newInstance()
- Bean 객체를 기반으로 RowMapper를 생성해주는 메서드
- BeanPropertySqlParameterSource
- BeanPropertySqlParameterSource는 SqlParameterSource 인터페이스를 구현한 클래스이다.
- SQL에 들어갈 SqlParameterSource 객체를 생성한다.
- Bean 객체를 Map 객체로 변환한다.
- 생성할 때 JavaBeans를 넣어주면 JavaBeans 변수명과 쿼리안의 :변수명을 자동으로 Mapping 시켜준다.
- Collections.singletonMap()
- key-value쌍이 단 하나인 Map을 만들어야 하는 경우 사용.
- Collections.emptyMap()
- 외부에서 반환한 데이터가 없거나 내부 로직에 의해 빈 데이터가 반환되어야 하는 경우 NullPointerException을 방지하기 위하여 반환 형태에 따라 List나 Map의 인스턴스를 생성하여 반환하여 처리해야 하는 경우에 사용한다.
- 후속 로직에서 size 메소드 등으로 체크를 하고 추가적인 값을 변경하지 않은 경우 매번 동일한 정적 인스턴스가 반환되므로 각 호출에 대해 불필요한 인스턴스 생성이 되지 않아 메모리 사용량을 줄일 수 있다.
- Collections.emptyList()나 Collections.emptyMap() 메소드로 반환된 객체에 add 혹은 put 메소드를 호출하는 경우 UnsupportedOperationException이 발생하므로 추가적인 데이터 수정을 하지 않는 경우에만 사용해야 한다.
참조
www.boostcourse.org/web316/lecture/254338/
https://www.boostcourse.org/web316/lecture/254339/
https://www.boostcourse.org/web316/lecture/254340/
https://www.boostcourse.org/web316/lecture/254341/
rio-kim.github.io/java/2018/06/27/make_easy_java_collection_code/
velog.io/@lacomaco/Spring-Jdbc-Template-%EC%8B%A4%EC%8A%B5-%EC%A0%95%EB%A6%AC
'Framework > Spring' 카테고리의 다른 글
Spring MVC 설정 (0) | 2021.01.06 |
---|---|
Spring MVC (0) | 2021.01.06 |
Spring JDBC (0) | 2021.01.04 |
Inversion of Control / Dependency Injection (0) | 2021.01.01 |
Spring Container metadata 설정 방법 (0) | 2021.01.01 |
댓글