스프링 DB 접근 기술 종류
- JDBC
- JDBCTemplate
- JPA
- Spring Data JPA
JDBC(Java Database Connectivity)
JDBC는 자바에서 데이터베이스를 접속할 수 잇도록 하는 자바 API이다. JDBC는 데이터 베이스에서 접근을 제공한다.
DataSource는 데이터베이스 커넥션을 획득할 때 사용하는 객체다.
기본적인 조회
@Override
publicMember save(Member member) {
String sql = "insert into member(name) values(?)";
Connection conn =null;
PreparedStatement pstmt =null;
ResultSet rs =null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, member.getName());
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if(rs.next()) {
member.setId(rs.getLong(1));
}else{
throw newSQLException("id 조회 실패");
}
returnmember;
}catch(Exception e) {
throw newIllegalStateException(e);
}finally{
close(conn, pstmt, rs);
}
}
@Override
publicOptional<Member> findById(Long id) {
String sql = "select * from member where id = ?";
Connection conn =null;
PreparedStatement pstmt =null;
ResultSet rs =null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, id);
rs = pstmt.executeQuery();
if(rs.next()) {
Member member =newMember();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
returnOptional.of(member);
}else{
returnOptional.empty();
}
}catch(Exception e) {
throw newIllegalStateException(e);
}finally{
close(conn, pstmt, rs);
}
}
@Override
publicList<Member> findAll() {
String sql = "select * from member";
Connection conn =null;
PreparedStatement pstmt =null;
ResultSet rs =null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
List<Member> members =newArrayList<>();
while(rs.next()) {
Member member =newMember();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
members.add(member);
}
returnmembers;
}catch(Exception e) {
throw newIllegalStateException(e);
}finally{
close(conn, pstmt, rs);
}
}
@Override
publicOptional<Member> findByName(String name) {
String sql = "select * from member where name = ?";
Connection conn =null;
PreparedStatement pstmt =null;
ResultSet rs =null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
rs = pstmt.executeQuery();
if(rs.next()) {
Member member =newMember();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
returnOptional.of(member);
}
returnOptional.empty();
}catch(Exception e) {
throw newIllegalStateException(e);
}finally{
close(conn, pstmt, rs);
}
}
privateConnection getConnection() {
returnDataSourceUtils.getConnection(dataSource);
}
private voidclose(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try{
if(rs !=null) {
rs.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
try{
if(pstmt !=null) {
pstmt.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
try{
if(conn !=null) {
close(conn);
}
}catch(SQLException e) {
e.printStackTrace();
}
}
private voidclose(Connection conn)throwsSQLException {
DataSourceUtils.releaseConnection(conn, dataSource);
}
JDBC Template
스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다. 하지만 SQL은 직접 작성해야 한다.
JDBC Template 구현방식
@Override
publicMember save(Member member) {
SimpleJdbcInsert jdbcInsert =newSimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
Map<String, Object> parameters =newHashMap<>();
parameters.put("name", member.getName());
Number key = jdbcInsert.executeAndReturnKey(newMapSqlParameterSource(parameters));
member.setId(key.longValue());
returnmember;
}
@Override
publicOptional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from member where id = ? ", memberRowMapper(), id);
returnresult.stream().findAny();
}
@Override
publicList<Member> findAll() {
returnjdbcTemplate.query("select * from member", memberRowMapper());
}
@Override
publicOptional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from member where name = ? ", memberRowMapper(), name);
returnresult.stream().findAny();
}
privateRowMapper<Member> memberRowMapper() {
return(rs, rowNum) -> {
Member member =newMember();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
returnmember;
};
}
JPA
JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준
ORM → Object-relational mapping
객체는 객체대로 설계를 진행하고 관계형 DB는 독립적으로 설계한다.
ORM은 중간에서 매핑시켜준다.
private finalEntityManager em;
publicJpaMemberRepository(EntityManager em) {
this.em = em;
}
@Override
publicMember save(Member member) {
em.persist(member);
returnmember;
}
@Override
publicOptional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
returnOptional.ofNullable(member);
}
@Override
publicOptional<Member> findByName(String name) {
List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class)
.setParameter("name", name)
.getResultList();
returnresult.stream().findAny();
}
@Override
publicList<Member> findAll() {
returnem.createQuery("Select m from Member m", Member.class).getResultList();
}
Spring Data JPA
JPA기반 데이터 액세스 계층에 대한 향상된 지원을 해준다. 데이터 액세스 기술을 사용하는 spring 기반 애플리케이션을 나은 방향으로 구축 할 수 있다.
public interfaceSpringDataJpaMemberRepositoryextendsJpaRepository<Member,Long>, MemberRepository {
//select m from Member m where m.name = ?
@Override
Optional<Member> findByName(String name);
}
마무리
JPA를 공부하기로 마음을 먹어서 JPA를 공부하고 Spring Data JPA를 더 깊이 있게 다루기로 하였다.
출처 : Inflearn - 김영한 강사님 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술