- mysql
- 자동증가 함수를 이용하자.(기본 컬럼에 primary key를 적용하면 Index 검사 매회 실행한다.)
- JDBC
- java.sql 패키지를 이용한 Database프로그래밍을 JDBC 프로그래밍이라고 합니다.
- java.sql의 핵심인터페이스를 보면, 구현하는 클래스를 자바는 제공하지 않는다.
- java를 만든 사람들은 DBMS와 상관없이 같은 방법으로 프로그래밍을 하길 원했다.
- 데이터베이스 프로그래밍에 대한 인터페이스를 정의하였다.
- DBMS마다 구현하는 방법은 다르다. 그렇다면? DB제작사에서 해당 인터페이스를 구현한 클래스를 제공한다. --> JDBC 드라이버(*.jar)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
SQL을 준비한다. (문자열을 준비)
- // role_id가 자동으로 생성된다면 다음과 같이 insert
insert into ROLE( description ) values ( 'ADMIN' )
// role_id가 자동으로 생성되지 않는다면
insert into ROLE (role_id, description) values ( 500, 'ADMIN' );
//프로그래밍을 한다.
//나쁜 예제 : + 연산자로 sql을 작성한다. SQL Injection 을 당할 수있다. 성능이 느려진다.
// DBMS에서 SQL을 실행하면, DBMS는 SQL을 분석한 후 실행한다. 분석하는 시간이 오래걸린다.
// 완전히 동일한 SQL은 이미 분석한 결과를 사용하여 실행한다. 분석을 한 결과는 캐싱에 남기 때문에.. (대소문자 구분한다.)
String sql = "insert into ROLE (role_id, description) values ( " + id + ", '" + description + " ');
//좋은예제
// 물음표 부분만 제외하고 분석됩니다. 개발자는 이 물음표에 나중에 값을 채운 후 실행한다.
// 물음표에 값을 채우는 것을 바인딩한다. 물음표의 순서는 1부터 시작한다.
String sql = "insert into ROLE (role_id, description) values ( ? , ? );
DB에서 SQL을 실행할 준비를 시킨다.
- PreparedStatement ps = conn.prepareStatement(sql);
//물음표부분을 바인딩 한다. 각각의 type에 맞게
ps.setInt(1, 500); // 첫번째 물음표에 500을 설정
ps.setString(2, "ADMIN") // 두번째 물음표에 ADMIN설정
SQL이 준비가 되어있다면, SQL을 실행한다.
- ps.execute()
int count = ps.excuteUpdate() // insert, update, delete sql을 실행
ResultSet rs = ps.executeQuery() // select를 실행. (0, 1건이 나올경우), 0건이상
Select일 경우
- 0,1건 Select일 경우
- ResultSet은 select한 결과를 참조하는 인터페이스다. ps.executeQuery()가 실행되면, 실행된 결과는 DBMS에 있다.
- // 한건을 읽어온다. 한건이라는 것은 record를 말한다. 여기서 record란 select다음에 나온 컬럼들을 말한다.
//읽어오지 못하면 false를 반환하고, 읽어오면 true를 반환한후 다음 레코드를 참조한다.
if(rs.next()) { //한건의 record를 읽어온다. select role_id, description from ROLE where role_id = ?
int roleId = rs.getInt(1); // 첫번째 컬럼의 값을 읽어온다.
String description = rs.getString(2); // 두번째 칼럼의 값을 읽어온다.
}
마지막 처리
- ResultSet을 close(), PreparedStatement를 close(), Conntction을 close();
Finally를 하거나 try - with - resources구문을 이용하거나 한다.
- DispatcherServlet는 ContextLoaderListener를 부모로 가진다. ContextLoaderListener는 자식에 접근 못한다.
- DispatcherServlet에서는 프리젠테이션 레이어 처리를 한다. Service, Repository 를 처리한다.
- DispatcherServlet 끼리는 서로 참조하지 못한다.
- ContextLoaderListener 구조
- DispatcherServlet -> path : /board
- DispatcherServlet -> path : /shop
- lombok Annotation
- 관련된 부분이 오류나면 intelliJ lombok 검색하면 셋팅하는 방법이 나온다.
- 컴파일 전에 자동으로 코드를 생성한다.
- @Setter
- @Getter
- @ToString
- @AllArgsConstructor
- @NoArgsConstructor
- Spring JDBC는 기존 JDBC프로그래밍을 아주 간단하게 할 수 있도록 도와준다.
- BeanPropertySqlParameterSource는 자동으로 Map객체를 만들어 준다.
- JdbcTemplate, dataSource 이 핵심객체이다.
- SimpleJdbcInsert는 insert를 쉽게 도와주는 객체이다.
- RowMapper는 한건의 recode를 쉽게 객체에 담아 줄수 있도록 도와준다.
jdbc에서 RsultSet으로부터 칼럼별로 값을 읽어오는 것을 도와주는 것
- 테이블에서 자동으로 id가 생성될 경우는 usingGeneratedKeyColumns를 사용한다.
- where 조건문이 없을때 Collections.emptyMap()를 활용한다.
- 자동으로 생성되는 id 는 executeAndReturnKey(params).intValue() 을 통해 pk를 반환할 수 있다.
- Map형태로 Collections.singletonMap를 사용하여 jdbc에 바인딩 한다.
- SqlParameterSource params = new BeanPropertySqlParameterSource(VO클래스)는 VO클래스에 있는 변수들을 자동으로 바인딩 해준다.
@Repository
public class RoleDao {
// Spring JDBC는 기존 JDBC기존 프로그래밍을 아주 간단하게 할 수 있도록 도와준다.
// JdbcTemplate, dataSource 이 핵심객체이다.
private NamedParameterJdbcTemplate jdbc;
// insert를 쉽게 도와주는 객체이다.
private SimpleJdbcInsert insertAction;
// RowMapper는 한건의 recode를 쉽게 객체에 담아 줄수 있도록 도와준다.
// jdbc에서 RsultSet으로부터 칼럼별로 값을 읽어오는 것을 도와주는 것
private RowMapper rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public RoleDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("ROLE"); //테이블명
// .usingGeneratedKeyColumns("id"); // 자동으로 id가 생성될 경우
}
public List selectAll() {
// Collections.emptyMap() -> new HashMap 과 같음
return jdbc.query("select role_id, description from ROLE order by role_id", Collections.emptyMap(), rowMapper);
}
public int insertRole(Role role){
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
// 자동으로 id를 생성할 경우에는 아래와 같이 생성된 pk를 반환할 수 있다.
// return insertAction.executeAndReturnKey(params).intValue();
int count = insertAction.execute(params);
return role.getRoleId();
}
public int deleteRole(int roleId){
Map params = Collections.singletonMap("roleId", roleId);
return jdbc.update("delete from ROLE where role_id = :roleId", params); //Map형식으로 활용 , :바인딩 처리
}
public int updateRole(Role role){
SqlParameterSource params = new BeanPropertySqlParameterSource(role); //자동으로 map객체를 만들어 준다.
return jdbc.update("update ROLE set description = :description where role_id = :roleId", params);
}
public Role selectRole(int roleId){
Map params = Collections.singletonMap("roleId", roleId);
try{
Role role = jdbc.queryForObject("select role_id, description from ROLE where role_id = :roleId", params, rowMapper);
return role;
}catch(){
return null;
}
}
}
0 개의 댓글:
댓글 쓰기