Search

Spring JDBC

Spring JDBC

β€’
JDBC & Spring JDBC μ˜μ‘΄μ„±
β€’
데이터 μ†ŒμŠ€ μ„€μ • & Spring JDBC 빈 등둝
β€’
인코딩 ν•„ν„°
β€’
ν…Œμ΄λΈ” 생성
β€’
λΉ„μ¦ˆλ‹ˆμŠ€ 둜직
β€’
νŠΈλžœμž­μ…˜

JDBC & Spring JDBC μ˜μ‘΄μ„± μ„€μ •

β€’
pom.xml
<!-- mysql λ“œλΌμ΄λ²„ --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.1.0</version> </dependency> <!-- Spring JDBC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework-version}</version> </dependency>
XML
볡사
β€’
pom.xml - lombok
<!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
XML
볡사
β€’
pom.xml (전체)
<?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 https://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.joeun</groupId> <artifactId>test</artifactId> <name>Spring-JDBC</name> <packaging>war</packaging> <version>1.0.0-BUILD-SNAPSHOT</version> <properties> <java-version>1.8</java-version> <org.springframework-version>5.3.10</org.springframework-version> <org.aspectj-version>1.9.7</org.aspectj-version> <!-- μ•„λž˜ λ²„μ „μœΌλ‘œ ν–ˆμ„ λ•Œ, @AfterReturning μ—μ„œ returning 이 계속 null 인 이슈 --> <!-- <org.springframework-version>5.0.7.RELEASE</org.springframework-version> --> <!-- <org.aspectj-version>1.5.4</org.aspectj-version> --> <org.slf4j-version>1.6.6</org.slf4j-version> </properties> <dependencies> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework-version}</version> <exclusions> <!-- Exclude Commons Logging in favor of SLF4j --> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework-version}</version> </dependency> <!-- AspectJ --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${org.aspectj-version}</version> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${org.slf4j-version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.15</version> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> </exclusions> <scope>runtime</scope> </dependency> <!-- @Inject --> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> <!-- Servlet --> <!-- <dependency> --> <!-- <groupId>javax.servlet</groupId> --> <!-- <artifactId>servlet-api</artifactId> --> <!-- <version>2.5</version> --> <!-- <scope>provided</scope> --> <!-- </dependency> --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- Test --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> <!-- mysql λ“œλΌμ΄λ²„ --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.1.0</version> </dependency> <!-- Spring JDBC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework-version}</version> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-eclipse-plugin</artifactId> <version>2.9</version> <configuration> <additionalProjectnatures> <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> </additionalProjectnatures> <additionalBuildcommands> <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> </additionalBuildcommands> <downloadSources>true</downloadSources> <downloadJavadocs>true</downloadJavadocs> </configuration> </plugin> <!-- μžλ°” 버전 : 1.6 β†’ 1.8 --> <!-- ν”ŒλŸ¬κ·ΈμΈ 버전 : 2.5.1 β†’ 3.8.1 --> <!-- parameter 인자 μΆ”κ°€ --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <mainClass>org.test.int1.Main</mainClass> </configuration> </plugin> </plugins> </build> </project>
XML
볡사

데이터 μ†ŒμŠ€ μ„€μ •, Spring JDBC 빈 등둝

β€’
root-context.xml
<!-- 데이터 μ†ŒμŠ€ 등둝 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://127.0.0.1:3306/joeun"></property> <property name="username" value="joeun"></property> <property name="password" value="123456"></property> </bean> <!-- JDBC Template 빈 등둝 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean>
XML
볡사

인코딩 ν•„ν„°

β€’
web.xml
<!-- 인코딩 ν•„ν„°(ν•œκΈ€κΉ¨μ§ 방지) --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
SQL
볡사

ν…Œμ΄λΈ” 생성

β€’
board.sql
CREATE TABLE `board` ( `no` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, `writer` varchar(100) NOT NULL, `content` text, `reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `upd_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `views` int NOT NULL DEFAULT '0', PRIMARY KEY (`no`) ) COMMENT='κ²Œμ‹œνŒ';
SQL
볡사

νŠΈλžœμž­μ…˜

νŠΈλžœμž­μ…˜μ€ λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ ν•œ λ²ˆμ— μˆ˜ν–‰λ˜μ–΄μ•Όν•˜λŠ” 일련의 μž‘μ—…μ„ μ˜λ―Έν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ μž‘μ—…μ€ λͺ¨λ‘ μ™„λ£Œλ˜κ±°λ‚˜ 아무것도 μˆ˜ν–‰λ˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€. νŠΈλžœμž­μ…˜μ€ λ°μ΄ν„°μ˜ 일관성과 무결성을 보μž₯ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ€ν–‰μ—μ„œ μ†‘κΈˆμ΄ λ°œμƒν•  λ•Œ μ†‘κΈˆκ³Ό λ™μ‹œμ— μž…κΈˆμ΄ λͺ¨λ‘ μ„±κ³΅μ μœΌλ‘œ 이루어져야 ν•˜λ©°, ν•˜λ‚˜μ˜ μž‘μ—…μ΄ μ‹€νŒ¨ν•˜λ©΄ λͺ¨λ“  μž‘μ—…μ€ λ‘€λ°±λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

νŠΈλžœμž­μ…˜ νŠΉμ§• - A.C.I.D

νŠΈλžœμž­μ…˜μ€ λ‹€μŒμ˜ νŠΉμ§•μ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€:
β€’
μ›μžμ„± (Atomicity): νŠΈλžœμž­μ…˜ λ‚΄μ˜ λͺ¨λ“  μž‘μ—…μ€ 일뢀라도 μ‹€νŒ¨ν•˜λ©΄ 전체 νŠΈλžœμž­μ…˜μ΄ λ‘€λ°±λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
β€’
일관성 (Consistency): νŠΈλžœμž­μ…˜μ΄ μˆ˜ν–‰λ˜κΈ° μ „κ³Ό 후에 λ°μ΄ν„°λ² μ΄μŠ€λŠ” μΌκ΄€λœ μƒνƒœμ—¬μ•Ό ν•©λ‹ˆλ‹€.
β€’
격리성 (Isolation): λ™μ‹œμ— μ‹€ν–‰λ˜λŠ” μ—¬λŸ¬ νŠΈλžœμž­μ…˜μ€ μ„œλ‘œ 영ν–₯을 주지 μ•Šκ³  λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
β€’
지속성 (Durability): νŠΈλžœμž­μ…˜μ΄ μ„±κ³΅μ μœΌλ‘œ μ™„λ£Œλ˜λ©΄ κ·Έ κ²°κ³ΌλŠ” 영ꡬ적으둜 μ €μž₯λ˜μ–΄μ•Ό ν•˜λ©°, μ‹œμŠ€ν…œ μž₯μ•  λ°œμƒ μ‹œμ—λ„ μœ μ§€λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
β€’
νŠΈλžœμž­μ…˜ μ˜μ‘΄μ„± μ„€μ •
β—¦
λ„€μž„ 슀페이슀 및 μŠ€ν‚€λ§ˆ μ„€μ •
β—¦
νŠΈλžœμž­μ…˜ κ΄€λ¦¬μž 빈 등둝
β—¦
νŠΈλžœμž­μ…˜ μ–΄λ…Έν…Œμ΄μ…˜ κΈ°λŠ₯ ν™œμ„±ν™”
β€’
μ„œλΉ„μŠ€ κ΅¬ν˜„ ν΄λž˜μŠ€μ— μ–΄λ…Έν…Œμ΄μ…˜ 적용
β—¦
@Transactional

νŠΈλžœμž­μ…˜ μ˜μ‘΄μ„± μ„€μ •

λ„€μž„ 슀페이슀

β€’
root-context.xml
xmlns:tx="http://www.springframework.org/schema/tx"
XML
볡사

μŠ€ν‚€λ§ˆ μ„€μ •

β€’
root-context.xml
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
XML
볡사

νŠΈλžœμž­μ…˜ κ΄€λ¦¬μž 빈 등둝

β€’
root-context.xml
<!-- νŠΈλžœμž­μ…˜ κ΄€λ¦¬μž 빈 등둝 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
XML
볡사

νŠΈλžœμž­μ…˜ μ–΄λ…Έν…Œμ΄μ…˜ κΈ°λŠ₯ ν™œμ„±ν™”

β€’
root-context.xml
<!-- νŠΈλžœμž­μ…˜ μ–΄λ…Έν…Œμ΄μ…˜ κΈ°λŠ₯ ν™œμ„±ν™” --> <tx:annotation-driven />
XML
볡사

μ„œλΉ„μŠ€ κ΅¬ν˜„ ν΄λž˜μŠ€μ— μ–΄λ…Έν…Œμ΄μ…˜ 적용

β€’
BoardServiceImpl.java
@Transactional @Override public void join(User user) throws Exception { userDAO.join(user); UserAuth userAuth = new UserAuth(); userAuth .setUserNo(user.getUserNo()); userAuth .setAuth("ROLE_USER"); userDAO.insertAuth(userAuth ); }
Java
볡사

λΉ„μ¦ˆλ‹ˆμŠ€ 둜직

β€’
controller
β—¦
BoardController.java
β€’
dto
β—¦
Board.java
β€’
dao
β—¦
BoardDAO.java
β€’
service
β—¦
BoardService.java
β—¦
BoardServiceImpl.java

controller

β€’
BoardController.java

BoardController.java

package com.joeun.test.controller; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.joeun.test.dto.Board; import com.joeun.test.service.BoardService; @Controller @RequestMapping("/board") public class BoardController { private static final Logger logger = LoggerFactory.getLogger(BoardController.class); @Autowired private BoardService boardService; // κ²Œμ‹œκΈ€ λͺ©λ‘ // @RequestMapping(value = "/list", method = RequestMethod.GET) @GetMapping("/list") // Spring 4.3 버전 λΆ€ν„° μ‚¬μš© public String list(Model model) throws Exception { List<Board> boardList = boardService.list(); model.addAttribute(boardList); return "board/list"; } // κ²Œμ‹œκΈ€ 쑰회 @GetMapping("/read") public String read(Model model, int no) throws Exception { Board board= boardService.select(no); model.addAttribute(board); return "board/read"; } // κ²Œμ‹œκΈ€ 등둝 @GetMapping("/insert") public String insert() throws Exception { return "board/insert"; } // κ²Œμ‹œκΈ€ 등둝 처리 @PostMapping("/insert") public String insert(Board board) throws Exception { int result = boardService.insert(board); return "redirect:/board/list"; } // κ²Œμ‹œκΈ€ μˆ˜μ • @GetMapping("/update") public String update(Model model, int no) throws Exception { Board board= boardService.select(no); model.addAttribute(board); return "board/update"; } // κ²Œμ‹œκΈ€ μˆ˜μ • 처리 @PostMapping("/update") public String update(Board board) throws Exception { int result = boardService.update(board); return "redirect:/board/list"; } // κ²Œμ‹œκΈ€ μ‚­μ œ 처리 @PostMapping("/delete") public String delete(int no) throws Exception { int result = boardService.delete(no); return "redirect:/board/list"; } }
Java
볡사

dto

β€’
Board.java

Board.java

package com.joeun.test.dto; import java.util.Date; import lombok.Data; @Data public class Board { private int no; private String title; private String writer; private String content; private Date regDate; private Date updDate; private int views; public Board() { } public Board(String title, String writer, String content) { this.title = title; this.writer = writer; this.content = content; } }
Java
볡사

dao

β€’
BoardDAO.java

BoardDAO.java

package com.joeun.test.dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import com.joeun.test.dto.Board; @Repository // 데이터 μ•‘μ„ΈμŠ€ 객체둜 빈 등둝 public class BoardDAO { @Autowired private JdbcTemplate jdbcTemplate; /** * κ²Œμ‹œκΈ€ λͺ©λ‘ 쑰회 * @return */ public List<Board> list() { String sql = " SELECT * FROM board "; List<Board> boardList = jdbcTemplate.query(sql, new RowMapper<Board>() { @Override public Board mapRow(ResultSet rs, int rowNum) throws SQLException { Board board = new Board(); board.setno( rs.getInt("no") ); board.setTitle( rs.getString("title") ); board.setWriter( rs.getString("writer") ); board.setContent( rs.getString("content") ); board.setRegDate( rs.getTimestamp("reg_date") ); board.setUpdDate( rs.getTimestamp("upd_date") ); board.setViews( rs.getInt("views") ); return board; } }); return boardList; } public Board select(int no) { String sql = " SELECT * FROM board WHERE no = ? "; // List<Board> boardList = jdbcTemplate.query(sql, new RowMapper<Board>() { // @Override // public Board mapRow(ResultSet rs, int rowNum) throws SQLException { // Board board = new Board(); // board.setno( rs.getInt("no") ); // board.setTitle( rs.getString("title") ); // board.setWriter( rs.getString("writer") ); // board.setContent( rs.getString("content") ); // board.setRegDate( rs.getTimestamp("reg_date") ); // board.setUpdDate( rs.getTimestamp("upd_date") ); // board.setViews( rs.getInt("views") ); // return board; // } // }, no); // // Board board = null; // if( boardList.isEmpty() ) // board = null; // else // board = boardList.get(0); // 2번째 방법 Board board = jdbcTemplate.queryForObject(sql, new RowMapper<Board>() { @Override public Board mapRow(ResultSet rs, int rowNum) throws SQLException { Board board = new Board(); board.setno( rs.getInt("no") ); board.setTitle( rs.getString("title") ); board.setWriter( rs.getString("writer") ); board.setContent( rs.getString("content") ); board.setRegDate( rs.getTimestamp("reg_date") ); board.setUpdDate( rs.getTimestamp("upd_date") ); board.setViews( rs.getInt("views") ); return board; } }, no); // 3번째 방법 // Object[] argList = new Object[]{no}; // Board board = jdbcTemplate.queryForObject(sql, argList, new RowMapper<Board>() { // @Override // public Board mapRow(ResultSet rs, int rowNum) throws SQLException { // Board board = new Board(); // board.setno( rs.getInt("no") ); // board.setTitle( rs.getString("title") ); // board.setWriter( rs.getString("writer") ); // board.setContent( rs.getString("content") ); // board.setRegDate( rs.getTimestamp("reg_date") ); // board.setUpdDate( rs.getTimestamp("upd_date") ); // board.setViews( rs.getInt("views") ); // return board; // } // }); return board; } public int insert(Board board) { String sql = " INSERT INTO board(title, writer, content) " + " VALUES ( ?, ?, ? ) "; Object[] args = new Object[] {board.getTitle(), board.getWriter(), board.getContent()}; int result = jdbcTemplate.update(sql, args); // int result = jdbcTemplate.update(sql, board.getTitle(), board.getWriter(), board.getContent()); return result; } public int update(Board board) { String sql = " UPDATE board " + " SET title = ? " + " ,writer = ? " + " ,content = ? " + " ,upd_date = now() " + " WHERE no = ? "; Object[] args = new Object[] {board.getTitle(), board.getWriter(), board.getContent(), board.getNo()}; int result = jdbcTemplate.update(sql, args); return result; } public int delete(int no) { String sql = " DELETE FROM board " + " WHERE no = ? "; Object[] args = new Object[] {no}; int result = jdbcTemplate.update(sql, args); return result; } }
Java
볡사

service

β€’
BoardService.java
β€’
BoardServiceImpl.java

BoardService.java

package com.aloha.spring.service; import java.util.List; import com.aloha.spring.dto.Board; public interface BoardService { // κ²Œμ‹œκΈ€ λͺ©λ‘ public List<Board> list() throws Exception; // κ²Œμ‹œκΈ€ 쑰회 public Board select(int no); // κ²Œμ‹œκΈ€ 등둝 public Integer insert(Board board) throws Exception; // κ²Œμ‹œκΈ€ μˆ˜μ • public Integer update(Board board) throws Exception; // κ²Œμ‹œκΈ€ μ‚­μ œ public Integer delete(int no) throws Exception; }
Java
볡사

BoardServiceImpl.java

package com.aloha.spring.service; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.aloha.spring.dao.BoardDAO; import com.aloha.spring.dto.Board; @Service // λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μ²˜λ¦¬ν•˜λŠ” μ„œλΉ„μŠ€ 클래슀둜 빈 등둝 public class BoardServiceImpl implements BoardService { private static final Logger logger = LoggerFactory.getLogger(BoardServiceImpl.class); @Autowired private BoardDAO boardDAO; @Override public List<Board> list() throws Exception { List<Board> boardList = boardDAO.list(); return boardList; } @Override public Board select(int no) { Board board = boardDAO.select(no); return board; } @Override public Integer insert(Board board) throws Exception { int result = boardDAO.insert(board); return result; } @Override public Integer update(Board board) throws Exception { int result = boardDAO.update(board); return result; } @Override public Integer delete(int no) throws Exception { int result = boardDAO.delete(no); return result; } }
Java
볡사