Arrays.copyOfRange(arr, x, y) : 배열을 x부터 y-1까지 복사해서 리턴Arrays.sort : 오름차순 정렬import java.util.Arrays;
public class KthNum01 {
public int[] solution(int[] array, int[][] commands) {
// commands의 길이만큼 answer 배열 생성
int[] answer = new int[commands.length];
int idx = 0;
for (int[] command : commands) {
// Arrays.copyOfRange(arr, x, y) : arr의 x부터 y-1값까지 복사
int[] sliceArr = Arrays.copyOfRange(array, command[0]-1, command[1]);
// 배열 정렬
Arrays.sort(sliceArr);
// answer[idx]에 값을 넣어준 후 idx+1
answer[idx++] = sliceArr[command[2]-1];
}
return answer;
}
}
PriorityQueue<Integer> pq = new PriorityQueue<>();pq.add(값) : 값을 pq에 넣음pq.poll() : 우선순위 값을 빼서 반환pq.forEach(item-> System.out.println(item));
👉 정렬 되지 않고 출력
while(!pq.isEmpty())
System.out.println(pq.poll());
👉 우선순위에 맞게 정렬되어 출력
final : 한번 초기화하면 바꿀 수 없는 것장점
이유
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
public class UserDaoFactory {
@Bean
public UserDao awsUserDao(){
return new UserDao(awsDataSource());
}
@Bean
DataSource awsDataSource() {
Map<String, String> env = System.getenv();
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(com.mysql.cj.jdbc.Driver.class);
dataSource.setUrl(env.get("DB_HOST"));
dataSource.setUsername(env.get("DB_NAME"));
dataSource.setPassword(env.get("DB_PASSWORD"));
return dataSource;
}
}
🔴 UserDao 클래스의 ConnectionMake를 모두 DataSource로 바꿔줌
private DataSource dataSource;
public UserDao(DataSource dataSource) {
this.dataSource = dataSource;
}
deleteAll
<public void deleteAll() throws SQLException, ClassNotFoundException {
jdbcContextWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
return conn.prepareStatement("delete from users");
}
});
}
add
🔴 add를 익명클래스로 적용하면 user를 생성자로 굳이 넘겨주지 않아도 됨
public void add(User user) throws SQLException, ClassNotFoundException {
jdbcContextWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users(id, name, password) VALUES (?, ?, ?)");
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
return pstmt;
}
});
}
jdbcContextWithStatementStrategy는 다른 Dao 예를들어 HospitalDao에서도 쓸 수 있음
👉 다른 Dao에서도 쓰기 위해 UserDao에서 분리하자
🔴 workContextWithStatementStrategy로 메소드명 변경
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JdbcContext {
private final DataSource dataSource;
public JdbcContext(DataSource dataSource) {
this.dataSource = dataSource;
}
public void workContextWithStatementStrategy(StatementStrategy stmt) throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = dataSource.getConnection();
ps = stmt.makePreparedStatement(conn);
ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
}
🔴 UserDao에 추가 한 후 기존 jdbcContextWithStatementStrategy메소드를 workWithStatementStrategy로 변경
🔴 jdbcContext를 생성자로 초기화
private final JdbcContext jdbcContext;
public UserDao(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcContext = new JdbcContext(dataSource);
}
🟢 deleteAll에서 sql문만 변수로 넣는 하나의 메소드 생성
public void executeSql(final String query) throws SQLException {
this.jdbcContext.workContextWithStatementStrategy(new StatementStrategy() {
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
return conn.prepareStatement(query);
}
});
}
public void deleteAll<() throws SQLException, ClassNotFoundException {
executeSql("delete from users");
}
🟢 executeSql을 JdbcContext로 옮기기
🟢 UserDao의 deleteAll this.jdbcContext.executeSql("delete from users");로 수정
🟢 queryForObject에 두번째 파라미터로 Integer.class를 넘겨줌으로써 int형의 데이터를 받아옴 (첫번째는 sql문)
🟢 RowMapper : 인터페이스 구현체로 ResultSet의 정보를 User에 매핑할 때 사용함
🔴 주의할 점
JdbcTemplate 적용 후 테스트 코드 실행 시 : 템플릿에서 예외처리를 해주기 때문에 UserDao 메소드의 throws 모두 지워주기
<import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import week5_221017_221021.day_221020.domain.User;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDao {
private final DataSource dataSource;
private final JdbcTemplate jdbcTemplate;
public UserDao(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void add(User user) {
jdbcTemplate.update("INSERT INTO users(id, name, password) values (?, ?, ?)",
user.getId(), user.getName(), user.getPassword());
}
public User findbyId(String id) {
String sql = "SELECT * from users where id = ?";
RowMapper<User> rowMapper = new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User(rs.getString("id"), rs.getString("name"), rs.getString("password"));
return user;
}
};
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}
public List<User> getAll() {
String sql = "select * from users order by id";
RowMapper<User> rowMapper = new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User(rs.getString("id"), rs.getString("name"), rs.getString("password"));
return user;
}
};
return jdbcTemplate.query(sql, rowMapper);
}
public void deleteAll() {
this.jdbcTemplate.update("delete from users");
}
public int getCount() {
return this.jdbcTemplate.queryForObject("select count(*) from users", Integer.class);
}
}
<import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import week5_221017_221021.day_221020.domain.User;
import java.sql.SQLException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = UserDaoFactory.class)
class UserDaoTest {
@Autowired
private ApplicationContext context;
private UserDao userDao;
private User user1;
private User user2;
private User user3;
@BeforeEach
public void setUp(){
userDao = context.getBean("awsUserDao", UserDao.class);
user1 = new User("1", "박성철", "1234");
user2 = new User("2", "이길원", "2345");
user3 = new User("3", "박범진", "3456");
}
@Test
void addAndGet() throws SQLException, ClassNotFoundException {
userDao.deleteAll();
assertEquals(0, userDao.getCount());
userDao.add(user1);
assertEquals(1, userDao.getCount());
userDao.add(user2);
assertEquals(2, userDao.getCount());
User selectedUser = userDao.findbyId(user1.getId());
assertEquals(user1.getName(), selectedUser.getName());
}
@Test
void userNull() {
assertThrows(EmptyResultDataAccessException.class, ()->{
userDao.findbyId("30");
});
}
@Test
@DisplayName("없을 때 빈 리스트를 리턴하는지, 있을 때 개수만큼 리턴하는지")
void getAllTest() {
userDao.deleteAll();
List<User> users = userDao.getAll();
assertEquals(0, users.size());
userDao.add(user1);
userDao.add(user2);
userDao.add(user3);
users = userDao.getAll();
assertEquals(3, users.size());
}
}
🟢 rowMapper가 중복되므로 메소드 밖으로 빼줌
🟢 이후 findbyId, getAll에서 제거
RowMapper<User> rowMapper = new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User(rs.getString("id"), rs.getString("name"), rs.getString("password"));
return user;
}
};
public User findbyId(String id) {
String sql = "SELECT * from users where id = ?";
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}
public List<User> getAll() {
String sql = "select * from users order by id";
return jdbcTemplate.query(sql, rowMapper);
}