스프링

 

DB 연동

1. JDBC 프로그래밍의 단점을 보완하는 스프링

    // 반복 되는 코드 1
    Member member;
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    
    try {
    	conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/chap14?");
    }
    // 반복 되는 코드 2
    finally {
			if (rs != null)
				try {rs.close();}catch(SQLException e2) {}
			if (pstmt != null)
				try {pstmt.close();}catch(SQLException e3) {}
			if (conn != null)
				try {conn.close();}catch(SQLException e3) {}	
    
    }

 

위에 코드를 보면 데이터 처리와는 상관없는 코드지만 JDBC 프로그래밍을 할 때 구조적으로 반복 된다.

구조적인 반복을 줄이기 위한 방법은 템플릿 메서드 패턴과 전략 패턴을 함께 사용하는 것이다.

스프링은 바로 이 두 패턴을 엮은 JdbcTemplate 클래스를 제공한다.

 

스프링이 제공하는 또 다른 장점은 트랜잭션 관리가 쉽다. 트랜잭션을 적용하고 싶은 메서드에 @Transactional

애노테이션을 붙이기만 하면 된다. ( 커밋 롤백 )

 

 

 

2. JDBC Template, DB 커넥션풀 사용 예제

 

 1). pom.xml

spring-jdbc : JdbcTemplate 등 JDBC 연동에 필요한 기능을 제공 ( 트랜잭션 기능 spring-tx모듈 자동으로 포함 )

tomcat-jdbc : DB 커넥션풀 기능을 제공

mysql-connector-java : MySql 연결에 필요한 JDBC 드라이버 제공

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.db</groupId>
  <artifactId>chap5-sp5</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>chap5-sp5</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.0.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.0.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-jdbc</artifactId>
			<version>8.5.27</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.33</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.25</version>
		</dependency>

		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
		</dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok-maven-plugin -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-maven-plugin</artifactId>
    <version>1.18.20.0</version>
    <scope>provided</scope>
</dependency>

    
	</dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

 

 

 2). DB 테이블 생성

 

1. root 계정에서 계정 생성 

create user 'jspexam'@'localhost' identified by 'jsppw';

 

 

2. 생성한 jspexam 계정 접속 후  데이터베이스 생성

create database (데이터베이스 이름) chap14 character set utf8mb4;

 

3. 데이터 베이스 권한 설정

grant all privileges on chap14.* to 'jspexam'@'localhost';

create user 'jspexam'@'%' identified by 'jsppw';
grant all privileges on chap14.* to 'jspexam'@'%';

 

4. 테이블 생성

create table chap14 (
memberid varchar(10) not null primary key,
password varchar(10) not null,
name varchar(20) not null,
email varchar(80)
)

 

5. 테스트용 테이블 데이터 추가

INSERT INTO member(memberid, password, name, email)
   VALUES ('test2', '1234', '김길순','hisnd@email.com')

 

 3). DataSource 설정 ( 커넥션 풀 관리 )

스프링이 제공하는 DB 연동 기능은 DataSource를 사용해서 DB Connection을 구한다. 

DB 연동에 사용할 DataSource를 스프링 빈으로 등록하고 DB연동 기능을 구현한 빈 객체는 DataSource를 주입받아 사용한다.Tomcat JDBC 모듈에서 DataSource 클래스를 제공 

package config;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import spring.MemberDao;

@Configuration
public class DbConfig {
	
	@Bean(destroyMethod = "close") // 빈이 소멸될 때 커넥션 풀을 닫도록 설정
	public DataSource dataSource() {
		
		DataSource ds = new DataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost:3306/chap14?"
				+"useSSL=true&useUnicode=true&characterEncoding=utf8");
		ds.setUsername("jspexam");
		ds.setPassword("jsppw");
		ds.setInitialSize(2); // 초기 커넥션 개수 지정
		ds.setMaxActive(10); // 최대 커넥션 개수 지정
		
		return ds;
		
	}
	
	@Bean
	public MemberDao memberDao() {
		return new MemberDao(dataSource());
	}
}

 

 3). DbQueryConfig ( DbQuery 빈을 설정하고 등록, DataSource 자동 주입 설정 ) 

package config;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DbQueryConfig {
	
	@Autowired
	private DataSource dataSource;
	// 클래스의 객체가 생성될 때 스프링은 dataSource 빈을 찾아서 자동으로 주입
	
	@Bean
	public DbQuery dbQuery() {
		return new DbQuery(dataSource);
	}
}

 

 4). DbQuery ( DAO, 데이터베이스 쿼리를 수행 ) 

package config;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.apache.tomcat.jdbc.pool.DataSource;

import spring.Member;

public class DbQuery {
	private DataSource dataSource;
	
	
	public DbQuery(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	// list 전체 출력
	public List selectAll() {
		Connection conn = null;
		List<Member> list = new ArrayList<>();
		try {
			conn = dataSource.getConnection();
			Statement stmt = conn.createStatement();
			String sql = "select * from member";
			ResultSet rs = stmt.executeQuery(sql);
			while(rs.next()) {
				list.add(new Member(
						rs.getString("memberid"),
						rs.getString("password"),
						rs.getString("name"),
						rs.getString("email")
						));
			}
			return list;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
		
		
	}
	// Select문 갯수
	public int count() {
		Connection conn = null;
		
		try {
			conn = dataSource.getConnection(); // 풀에서 구함
			try(Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("select count(*) from MEMBER")){
				rs.next();
				return rs.getInt(1);
			}
			
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally {
			if (conn != null)
				try {
					conn.close(); // 풀에 반환 
				}catch (SQLException e) {
					
				}
		}
		
		
		
	}
	
}

 

 

 5). 실행 

package main;



import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import config.DbConfig;
import config.DbQuery;
import config.DbQueryConfig;
import spring.Member;



public class Ex1 {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ctx =
				new AnnotationConfigApplicationContext
				(DbConfig.class, DbQueryConfig.class);
		
		DbQuery dbQuery = ctx.getBean("dbQuery",DbQuery.class);
		int c1 = dbQuery.count();
		System.out.println(c1);
		
		List<Member> list = dbQuery.selectAll();
		for(Member member : list) {
			System.out.println(member);
		}

	}

}

 

 

 

 

JdbcTemplate(템플릿)을 이용한 쿼리 실행

스프링을 사용하면 DataSource나 Connection, Statemement, ResultSet을 직접 사용하지 않고 JdbcTemplate을 

이용해서 편리하게 쿼리를 실행할 수 있다.

 1). DB정보 토대로 DTO 만들기 ( CRUD하기 위해서 ) lombok 사용 

package spring;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Member {
	private String memberid;
	private String password;
	private String name;
	private String email;
	
	
	
}

 

 2). JdbcTemplate 생성하기 ( DAO에 생성, DAO 생성자에 DataSource를 주입받도록 구현 ) 

여기서 주의해야 할 점은 마이바티스랑 틀리게 추가, 업데이트, 삭제 시 동일하게 jdbcTemplate.update 사용

package spring;


import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

public class MemberDao {
	private JdbcTemplate jdbcTemplate;
	
	public MemberDao(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}
	
	// select 갯수 구현 
	public int count() {
		Integer count = jdbcTemplate.queryForObject("select count(*) from member", Integer.class);
	return count;
	}
	
	// insert 구현
	public void insert(Member member) {
		String sql = "insert into member(memberid, password, name, email)"
				+ "values (?,?,?,?)";
		jdbcTemplate.update(sql,
				member.getMemberid(), member.getPassword(),
				member.getName(), member.getEmail()
				);
	}
	
	// 업데이트 구현
	public void update(Member member) {
	    String sql = "update member set password=?, name=?, email=? "
	            + "where memberid = ?";

	    jdbcTemplate.update(sql,
	            member.getPassword(),
	            member.getName(), member.getEmail(), member.getMemberid()
	    );
	    System.out.println("업데이트 완료");
	}
	
	// 삭제 구현 
	public void delete(String id) {
		String sql = "delete from member where memberid = ?";
		
		jdbcTemplate.update(sql, id);
		System.out.println("삭제완료");
	}
	
	// List 전체 목록 출력 구현
	public List<Member> selectAll(){
		List<Member> result = jdbcTemplate.query("select * from member",
				new RowMapper<Member>() {

					@Override
					public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
						Member member = new Member(
													rs.getString("memberid"),
													rs.getString("email"),
													rs.getString("password"),
													rs.getString("name"));
						return member;
					}
			
		});
		return result;
	}
}

 

 

3). 실행

package main;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import config.DbConfig;
import config.DbQueryConfig;
import spring.Member;
import spring.MemberDao;

public class TestMemberDao {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ctx =
				new AnnotationConfigApplicationContext(DbConfig.class, DbQueryConfig.class);
		MemberDao memberDao = ctx.getBean("memberDao", MemberDao.class);
		System.out.println(memberDao.count());
		
		 // 삭제
		//memberDao.delete("test4");
		
		// 조회
//		List<Member> list = memberDao.selectAll();
//		for(Member member : list) {
//			System.out.println(member);
//		}
		
		 // 생성 
		//memberDao.insert(new Member("test4", "111", "구마적", "sed@scd.com"));
		
		// 업데이트
		Member member = new Member("test4", "222", "신마적","ewewe@dd.com");
		memberDao.update(member);
		
		
	}

}

 

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-08-04 56일차  (0) 2023.08.04
2023-08-03 55일차  (0) 2023.08.03
2023-08-01 53일차  (0) 2023.08.01
2023-07-31 52일차  (0) 2023.07.31
2023-07-28 51일차  (0) 2023.07.28

+ Recent posts