Spring

[Spring] Spring JDBC + 실습

oink24 2023. 9. 21. 14:20

 

 

 

 

 

1. JDBC란?

(Java JDBC 프로그래밍 정리 링크)

(Java JDBC 실습)

(JSP JDBC 실습)

  • JDBC는 Java의 데이터베이스 Access 기술
  • Entity 클래스와 Annotation을 이용하는 최신 ORM 기술도 내부적으로 JDBC를 이용
  • 간단한 SQL을 실행 할 때도 중복된 코드가 반복적으로 사용되는 Low level 기술로 인식

 

 

 

2. Data Access 계층

  • Data Access 계층은 DAO 패턴을 적용, 비즈니스 로직과 데이터 액세스 로직을 분리하는 것이 원칙 (Service와 DAO)
  • DataSource는 DB 커넥션 정보를 갖는 객체로 DB Connection Pool 기능 제공
  • Spring Data는 데이터 저장소의 특수성을 유지하면서 데이터 접근을 위한 친숙하고 일관된 Spring 기반의 프로그래밍 모델을 제공하는 프로젝트
  • Spring Data는 데이터 액세스와 관련된 많은 하위 프로젝트(module) 포함

MongoDB : NoSQL

Redis : 메모리 기반 DB

 

 

 

3. Spring Data JDBC

  • Spring Data JDBC는 스프링 프레임워크에서 제공하는 JDBC 기반의 데이터 액세스 기술
  • Spring Data JDBC는 기존 JDBC의 단점을 보완한 간결한 형태의 API 지원
    기존의 JDBC 단점? 쿼리 하나 실행하는데에 너무 반복적인 일련의 코드가 필요함
  • JdbcTemplate은 JDBC의 모든 기능을 지원하는 클래스

 

 

 


 

 

<< Spring data JDBC 관련라이브러리 추가 >>

  • Spring JDBC

Spring 관련 라이브러리들이 5.3.30으로 맞춰져있으니 맞춰주는게 좋음

https://mvnrepository.com/artifact/org.springframework/spring-jdbc/5.3.30

 

  • MySQL Connector/J

DBMS를 MySQL 사용하므로

https://mvnrepository.com/artifact/com.mysql/mysql-connector-j/8.1.0

 

  • Apache Commons DBCP

https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2/2.10.0

 

하고 pom.xml, application.xml 설정파일 설정해주고, view 파일 생성

(이때 주의할점!!!! View Resolver 경로 잡아놓은데로 뷰 생성해야함)

 

 

---

각 컨트롤러별로 하나의 서비스가 나온다고 생각하면됨

(main같은 경우는 서비스가 필요없음... 페이지만 띄우는거라..)

 

어노테이션 각각 붙여주기

 

 

------------- User1Service

Service 싱글톤 필요X

어노테이션이 다 알아서 관리함

User1DAO라는 스프링객체를 컨테이너에 등록해서 주입받는 식

서비스에서 DAO 주입받아야하니까 어노테이션 제발 잊지말기.. @Autowired

 

 

------------- User1Controller

컨트롤러에서도 서비스 선언해주어야 함. 사용해야하니까.!

 

매개변수에 @ModelAttribute 생략되어있는것!

 

 

------------- User1DAO 설정

JdbcTemplate 주입받을건데 스프링 컨테이너(application.xml)에 생성되어있지 않음.

생성이 되어있어야 쟤네가 관리를해서 주입을 받을 수 있으니까.. 생성해주어야 함.

 

<bean> = 스프링 컨테이너가 관리하는 객체

따라서 빈을 만들어주어야 함.

https://docs.spring.io/spring-framework/docs/5.3.30/reference/html/data-access.html#jdbc-JdbcTemplate-idioms

<!-- DataSource 설정 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://<!-- ip주소 -->:3306/<!-- 테이블명 -->"/>
    <property name="username" value="<!-- 사용자 -->"/>
    <property name="password" value="<!-- 비밀번호 -->"/>
</bean>

<!-- JdbcTemplate 설정 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>

DataSource를 설정해주고 이를 참조하여 JdbcTemplate을 설정해줌

우클릭 - Copy Qualified Name 해서 속성(<property>) 설정까지 해주면 된다.

 

 

======================================

 

--- 대망의 데이터 INSERT하기

- User1Controller.java

등록 뷰 페이지 띄우기

폼에서 전송한걸 받아서 리스트로 리다이렉트

 

- User1DAO.java

jdbc.update 혹은 jdbc.query 두가지를 대부분 사용하는데 Java/JSP JDBC와 마찬가지로 select 시에만 query, 나머지(insert, update, delete) 시에는 jdbc.update를 사용해주면 된다.

쿼리문을 먼저 작성해주고 쿼리 파라미터에 맞게 값을 넣어주어야 하는데 여러 값을 넣어야하므로 오브젝트 배열을 생성 후 jdbc.update(쿼리문, 바인딩)으로 전달해주면 끝

 

 

=================================================

 

--- list 출력하기 (SELECT)

- User1Controller.java

리스트 뷰 페이지를 띄워줄건데 서비스의 selectUser1s를 통해 리스트에 출력할 리스트를 받고,

뷰에서는 Model클래스를 이용해서 참조해야하기 때문에 model.addAttribute()

 

 

- User1DAO.java

원래는 ResultSet으로 반복문 돌려서 리스트에 저장 후 그 리스트를 반환했었는데 이를 RowMapper를 이용해서 처리한다.

 

- User1RowMapper.java

User1RowMapper 클래스 만들어주고

그리고

현재 행의 값을 매핑해주는데, ResultSet의 각 데이터 행을 매핑하기 위해 mapRow 메서드를 구현해야 한다.

 

=============================

 

--- 수정 (SELECT, UPDATE)

- User1Controller.java

수정페이지 클릭할 때 uid를 전송해서 수정할 uid를 받음.

수정 뷰 페이지 띄워주기

마찬가지로 뷰에서는 모델로 참조해서 값을 띄울거기때문에 model.addAttribute()

model.addAttribute(인자값) 하나면?! 저 타입(User1DTO)가 attributeName이 됨. (컴포넌트처럼 소문자로!) 즉, user1DTO

 

- User1DAO.java

수정할 값 조회

바인딩해야할 값이 하나이므로 uid넣어주면되고, dto로 반환하기 위해 jdbc.queryForObject() 이용

 

- User1Controller.java

modify.jsp :: 수정 view

수정한 데이터들이 post방식으로 들어옴

UPDATE처리 후 리스트로 리다이렉트

 

- User1DAO.java

마찬가지로 바인딩해야하는 값이 여러개이므로 오브젝트 배열을 사용해야한다.

 

 

 

==============================

 

--- 삭제 (DELETE)

리스트에서 삭제를 클릭하면,

- User1Controller.java

서비스-삭제 후, 리스트로 리다이렉트

- User1DAO.java

 

더보기
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Ch05::index</title>
    </head>
    <body>
        <h3>Ch05.Spring JDBC 실습</h3>

        <h4>user1 실습</h4>
        <a href="/Ch05/user1/register">user1 등록</a>
        <a href="/Ch05/user1/list">user1 목록</a>
    </body>
</html>
더보기
package ch05.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MainController {
	
	@GetMapping(value = {"/", "/index"})
	public String index() {
		return "/index";
	}
}
더보기
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>user1::register</title>
    </head>
    <body>
        <h3>user1 등록</h3>

        <a href="/Ch05/index">메인</a>
        <a href="/Ch05/user1/list">user1 목록</a>
        <form action="/Ch05/user1/register" method="post">
            <table border="1">
                <tr>
                    <td>아이디</td>
                    <td><input type="text" name="uid"></td>
                </tr>
                <tr>
                    <td>이름</td>
                    <td><input type="text" name="name"></td>
                </tr>
                <tr>
                    <td>휴대폰</td>
                    <td><input type="text" name="hp"></td>
                </tr>
                <tr>
                    <td>나이</td>
                    <td><input type="number" name="age"></td>
                </tr>
                <tr>
                    <td colspan="2" align="right"><input type="submit" value="등록하기"></td>
                </tr>
            </table>
        </form>
    </body>
</html>
더보기
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>user1::list</title>
    </head>
    <body>
        <h3>user1 목록</h3>

        <a href="/Ch05/index">메인</a>
        <a href="/Ch05/user1/register">user1 등록</a>
        <form action="/Ch05/user1/register" method="post">
            <table border="1">
                <tr>
                    <td>아이디</td>
                    <td>이름</td>
                    <td>휴대폰</td>
                    <td>나이</td>
                    <td>관리</td>
                </tr>
                <c:forEach var="user" items="${users}">
                <tr>
                    <td>${user.uid}</td>
                    <td>${user.name}</td>
                    <td>${user.hp}</td>
                    <td>${user.age}</td>
                    <td>
                        <a href="/Ch05/user1/modify?uid=${user.uid}">수정</a>
                        <a href="/Ch05/user1/delete?uid=${user.uid}">삭제</a>
                    </td>
                </tr>
                </c:forEach>
            </table>
        </form>
    </body>
</html>
더보기
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>user1::modify</title>
    </head>
    <body>
        <h3>user1 수정</h3>

        <a href="/Ch05/index">메인</a>
        <a href="/Ch05/user1/modify">user1 수정</a>
        <form action="/Ch05/user1/modify" method="post">
            <table border="1">
                <tr>
                    <td>아이디</td>
                    <td><input type="text" name="uid" value="${user1DTO.uid}" readonly="readonly"></td>
                </tr>
                <tr>
                    <td>이름</td>
                    <td><input type="text" name="name" value="${user1DTO.name}"></td>
                </tr>
                <tr>
                    <td>휴대폰</td>
                    <td><input type="text" name="hp" value="${user1DTO.hp}"></td>
                </tr>
                <tr>
                    <td>나이</td>
                    <td><input type="number" name="age" value="${user1DTO.age}"></td>
                </tr>
                <tr>
                    <td colspan="2" align="right"><input type="submit" value="등록하기"></td>
                </tr>
            </table>
        </form>
    </body>
</html>
더보기
package ch05.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import ch05.dto.User1DTO;
import ch05.service.User1Service;

@Controller
public class User1Controller {
	
	@Autowired
	private User1Service service;
	
	@GetMapping("/user1/register")
	public String register() {
		return "/user1/register";
	}
	@PostMapping("/user1/register")
	public String register(User1DTO dto) {
		service.insertUser1(dto);
		return "redirect:/user1/list";
	}
	
	@GetMapping("/user1/list")
	public String list(Model model) {
		
		List<User1DTO> users = service.selectUser1s();
		model.addAttribute("users", users);
		
		return "/user1/list";
	}
	
	@GetMapping("/user1/modify")
	public String modify(@RequestParam("uid") String uid, Model model) {
		
		// 수정할 값 조회
		User1DTO user = service.selectUser1(uid);
		model.addAttribute(user);
		
		return "/user1/modify";
	}
	@PostMapping("/user1/modify")
	public String modify(@ModelAttribute User1DTO dto) {
		
		service.updateUser1(dto);
		
		return "redirect:/user1/list";
	}
	
	@GetMapping("/user1/delete")
	public String delete(String uid) {
		
		service.deleteUser1(uid);
		return "redirect:/user1/list";
	}
}
더보기
package ch05.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ch05.dao.User1DAO;
import ch05.dto.User1DTO;

@Service
public class User1Service {
	
	@Autowired
	private User1DAO dao;

	public void insertUser1(User1DTO dto) {
		dao.insertUser1(dto);
	}
	public User1DTO selectUser1(String uid) {
		return dao.selectUser1(uid);
	}
	public List<User1DTO> selectUser1s() {
		return dao.selectUser1s();
	}
	public void updateUser1(User1DTO dto) {
		dao.updateUser1(dto);
	}
	public void deleteUser1(String uid) {
		dao.deleteUser1(uid);
	}
}
더보기
package ch05.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import ch05.dto.User1DTO;

@Repository
public class User1DAO {
	
	@Autowired
	private JdbcTemplate jdbc;
	
	public void insertUser1(User1DTO dto) {
		
		String sql = "INSERT INTO `user1` VALUES (?,?,?,?)";
		// 쿼리파라미터 순서에 맞게 바인딩
		Object[] params = {dto.getUid(), dto.getName(), dto.getHp(), dto.getAge()};
		
		jdbc.update(sql, params);
	}
	
	public User1DTO selectUser1(String uid) {
		
		String sql = "SELECT * FROM `user1` WHERE `uid`=?";
		User1DTO dto = jdbc.queryForObject(sql, new User1RowMapper(), uid);
		
		return dto;
	}
	
	public List<User1DTO> selectUser1s() {
		
		String sql = "SELECT * FROM `user1`";
		List<User1DTO> users = jdbc.query(sql, new User1RowMapper());
		
		return users;
	}
	
	public void updateUser1(User1DTO dto) {
		
		String sql = "UPDATE `user1` SET `name`=?, `hp`=?, `age`=? WHERE `uid`=?";
		Object[] params = {
				dto.getName(),
				dto.getHp(),
				dto.getAge(),
				dto.getUid()
		};
		
		jdbc.update(sql, params);
	}
	
	public void deleteUser1(String uid) {
		
		String sql = "DELETE FROM `user1` WHERE `uid`=?";
		jdbc.update(sql, uid);
	}
}
더보기
package ch05.dto;

public class User1DTO {
	
	private String uid;
	private String name;
	private String hp;
	private int age;
	
	public String getUid() {
		return uid;
	}
	public void setUid(String uid) {
		this.uid = uid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getHp() {
		return hp;
	}
	public void setHp(String hp) {
		this.hp = hp;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
더보기
package ch05.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import ch05.dto.User1DTO;

public class User1RowMapper implements RowMapper<User1DTO> {

	@Override
	public User1DTO mapRow(ResultSet rs, int rowNum) throws SQLException {
		
		User1DTO dto = new User1DTO();
		
		dto.setUid(rs.getString(1));
		dto.setName(rs.getString(2));
		dto.setHp(rs.getString(3));
		dto.setAge(rs.getInt(4));
		
		return dto;
	}
}