MyBatis
MyBatis λν΄μ μμλ³΄κ³ κ°λ¨νκ² κ²μν κΈ°λ₯μ ꡬννλ μ€μ΅κΉμ§ μ§νν΄ λ³΄λλ‘ νκ² μ΅λλ€.
β’
Mybatis
β’
νλ‘μ νΈ κ΅¬μ‘°
β’
μ€νλ§ λΆνΈμμ MyBatis μ¬μ©
β’
μμ‘΄μ± μΆκ°
β¦
build.gradle
β¦
pom.xml
β’
λ§μ΄λ°ν°μ€ μ€μ νμΌ - mybatis-config.xml
β’
νλ‘μ νΈ μ€μ - application.properties
β’
DB ꡬμΆ
β’
λ‘μ§ μμ±
β¦
DTO μμ±
β¦
SQL Mapper μμ±
β¦
Mapper μΈν°νμ΄μ€ μμ±
β¦
Service μμ±
β¦
Controller μμ±
β¦
View μμ±
MyBatis
λ§μ΄λ°ν°μ€λ κ°λ°μκ° μ§μ ν SQL, μ μ₯νλ‘μμ κ·Έλ¦¬κ³ λͺκ°μ§ κ³ κΈ λ§€νμ μ§μνλ νΌμμ€ν΄μ€ νλ μμν¬μ΄λ€.
μλ° νλ‘κ·Έλ¨μμ λ°μ΄ν°λ² μ΄μ€ μ°λμ μν΄μ, JDBC λλΌμ΄λ²λ₯Ό μ¬μ©νλ©΄, Java μ½λμ SQL μ½λκ° κ°μ΄ μ¬μ©λλκΉ, μ μ§λ³΄μμ±μ΄ μ νλ©λλ€.
κ·Έλμ Mybatis λ₯Ό μ¬μ©νλ©΄, Java μ½λμμ SQL μ λΆλ¦¬ν΄μ XML κ΄λ¦¬λ₯Ό νκ³ , μλ°μ μΈν°νμ΄μ€ νΈμΆμ λ°λΌμ XML μ νΉμ id μ ν΄λΉνλ 쿼리λ₯Ό μ€νμν° SQL Mapper λ°©μμΌλ‘ DB μ°λμ ν μ μμ΅λλ€.
νλ‘μ νΈ κ΅¬μ‘°
π¦Β spring-mybatis
β
ββββπjava
β ββββπcom.aloha.springmybatis
β β
β ββββπcontroller
β β ββββπBoardController.java
β β
β ββββπdto
β β ββββπBoard.java
β β
β ββββπservice
β β β
β β ββββπBoardService.java
β β ββββπBoardServiceImpl.java
β β
β ββββπmapper
β ββββπBoardMapper.java
β
ββββπresources
β πapplication.properties
β πmybatis-config.xml
β
ββββπcom.aloha.springmybatis.mapper
βββββπBoardMapper.xml
Plain Text
볡μ¬
μ€νλ§ λΆνΈμμ MyBatis μ¬μ©
SpringBoot μμ MyBatisλ₯Ό μ¬μ©ν λμλ
μ£Όλ‘ Gradle λΉλλꡬμ μ€μ νμΌμ build.gradle λλ
Maven λΉλλꡬμ μ€μ νμΌμΈ pom.xml μ μμ‘΄μ±μ μΆκ°νμ¬ μ¬μ©ν©λλ€
μμ‘΄μ± μΆκ°
β’
build.gradle
β’
pom.xml
build.gradle
β’
mysql λλΌμ΄λ² μμ‘΄μ±
β’
MyBatis μμ‘΄μ±
β’
build.gradle μ 체μ½λ
mysql λλΌμ΄λ² μμ‘΄μ±
runtimeOnly 'com.mysql:mysql-connector-j'
Java
볡μ¬
MyBatis μμ‘΄μ±
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
Java
볡μ¬
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
볡μ¬
pom.xml
β’
mysql λλΌμ΄λ² μμ‘΄μ±
β’
MyBatis μμ‘΄μ±
β’
build.gradle μ 체μ½λ
mysql λλΌμ΄λ² μμ‘΄μ±
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
<scope>runtime</scope>
</dependency>
XML
볡μ¬
MyBatis μμ‘΄μ±
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>mybatis</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
XML
볡μ¬
λ§μ΄λ°ν°μ€ μ€μ νμΌ - mybatis-config.xml
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- μ€μ -->
<settings>
<!-- μΈλμ€μ½μ΄ μΌμ΄μ€μΈ 컬λΌμ μΉ΄λ© μΌμ΄μ€λ‘ λ³ννλ μ€μ -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- νμ
λ³μΉ μ€μ -->
<typeAliases>
<!-- ν
μ΄λΈκ³Ό 맀νν DTOκ° μλ ν¨ν€μ§ κ²½λ‘ μ§μ -->
<package name="com.aloha.mybatis.dto"/>
</typeAliases>
</configuration>
XML
볡μ¬
mapUnderscoreToCamelCase
<settings>
<!-- μΈλμ€μ½μ΄ μΌμ΄μ€μΈ 컬λΌμ μΉ΄λ© μΌμ΄μ€λ‘ λ³ννλ μ€μ -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
XML
볡μ¬
μ΄λ κ² μμ±νλ©΄ λ°μ΄ν°λ² μ΄μ€μ μΈλμ€μ½μ΄ μΌμ΄μ€λ₯Ό λ³λλ‘ μλ°μ μΉ΄λ© μΌμ΄μ€λ‘ λ³ννμ§ μμλ μλμΌλ‘ ν
μ΄λΈμ 컬λΌλͺ
μ κ°μ²΄μ λ³μλ‘ λ§€ν ν μ μκ² λ³νν΄μ€λλ€.
typeAliases - package
<typeAliases>
<!-- ν
μ΄λΈκ³Ό 맀νν DTOκ° μλ ν¨ν€μ§ κ²½λ‘ μ§μ -->
<package name="com.aloha.mybatis.dto"/>
</typeAliases>
XML
볡μ¬
μ΄ μ€μ μ ꡬμ±νλ©΄ Mapper νμΌμμ resultType μμ±μ΄ ν¨ν€μ§λΆν° ν΄λμ€κΉμ§ λ€ μ§μ νμ§ μμλ, 맀νν κ°μ²΄κ° μλ ν¨ν€μ§λ₯Ό μ¬κΈ° μ€μ ν¨μΌλ‘μ¨, κ°μ²΄ μ΄λ¦λ§ μμ±ν΄λ μ‘°νμ κ²°κ³Όλ₯Ό κ°μ²΄μ λ°λ‘ 맀νν μ μμ΅λλ€.
<!-- κ²μκΈ μ‘°ν -->
<select id="select" resultType="com.aloha.mybatis.dto.Board">
XML
볡μ¬
μ΄ μ€μ μ μ¬μ©νμ§ μμΌλ©΄ Β λ€μκ³Ό κ°μ΄ ν¨ν€μ§λΆν° ν΄λμ€λͺ
κΉμ§ resultType μμ±μ λ€ μμ±ν΄μΌ λμ§λ§, μ΄ μ€μ μ μ¬μ©νλ©΄ κ°μ²΄λͺ
λ§ μμ±ν΄λ λ©λλ€.
<!-- κ²μκΈ μ‘°ν -->
<select id="select" resultType="Board">
XML
볡μ¬
λ°λΌμ μ‘°ν κ²°κ³Όλ₯Ό 맀νν κ°μ²΄λ€μ΄ μλ ν¨ν€μ§λ€μ 미리 μ§μ ν΄ λμΌλ©΄ . λ€μκ³Ό κ°μ΄ κ°κ²°νκ² μμ± κ°μ μμ±ν μ μμ΅λλ€ .
νλ‘μ νΈ μ€μ - application.properties
DB λλΌμ΄λ²μ MyBatisμ μ€μ μ νλ‘μ νΈμ μλ €μ£ΌκΈ° μν΄μλ Β application.properties νμΌμ λ€μκ³Ό κ°μ΄ λ°μ΄ν° μμ€μ Mybatis κ΄λ ¨ μ€μ μ μμ±ν΄μΌ ν©λλ€.
β’
λ°μ΄ν° μμ€ μ€μ
β’
mybatis-config.xml μ€μ
λ°μ΄ν° μμ€ μ€μ
# λ°μ΄ν° μμ€ - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
Plain Text
볡μ¬
mybatis-config.xml μ€μ
# Mybatis μ€μ
# Mybatis μ€μ κ²½λ‘ : ~/resources/mybatis-config.xml
mybatis.config-location=classpath:mybatis-config.xml
# Mybatis λ§€νΌ νμΌ κ²½λ‘ : ~/λ©μΈν¨ν€μ§/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
볡μ¬
β’
classpath: λΌκ³ μ§μ νλ©΄, ~/resources κ²½λ‘ νμλΆν° κ²½λ‘λ₯Ό μ§μ ν μ μλ€.
β’
classpath:mybatis/mapper/**/**.xml λΌκ³ μ§μ νλ©΄, ~/resources κ²½λ‘λΆν° λͺ¨λ κ²½λ‘μ λͺ¨λ νμ νμΌμ νμ₯μκ° .xml μ΄λ©΄ λ§μ΄λ°ν°μ€ 맀νΌ(SQL) νμΌλ‘ μΈμνλλ‘ μ§μ νλ€.
mybatis-config.xml μ€μ νμΌ μμ΄ μ μ©νκΈ°
# 컬λΌλͺ
μ λ³μλͺ
μΌλ‘ μλ맀ν : board_no β‘ boardNo
mybatis.configuration.map-underscore-to-camel-case=true
# resultType μμ±μμ dto κ°μ²΄ (ν¨ν€μ§.ν΄λμ€λͺ
) β‘ (ν΄λμ€λͺ
)
mybatis.type-aliases-package=com.aloha.mybatis.dto
# Mybatis λ§€νΌ νμΌ κ²½λ‘ : ~/λ©μΈν¨ν€μ§/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
볡μ¬
application.properties
spring.application.name=spring-mybatis
# λ°μ΄ν° μμ€ - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
# Mybatis μ€μ
# Mybatis μ€μ κ²½λ‘ : ~/resources/mybatis-config.xml
# mybatis.config-location=classpath:mybatis-config.xml
# 컬λΌλͺ
μ λ³μλͺ
μΌλ‘ μλ맀ν : board_no β‘ boardNo
mybatis.configuration.map-underscore-to-camel-case=true
# resultType μμ±μμ dto κ°μ²΄ (ν¨ν€μ§.ν΄λμ€λͺ
) β‘ (ν΄λμ€λͺ
)
mybatis.type-aliases-package=com.aloha.mybatis.dto
# Mybatis λ§€νΌ νμΌ κ²½λ‘ : ~/λ©μΈν¨ν€μ§/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
볡μ¬
DB ꡬμΆ
μ΄λ² μ€μ΅μμλ MySQLμ λλΌμ΄λ²λ₯Ό μ¬μ©ν©λλ€ . MySQLμ μ€μΉκ° νμνκ±°λ . κΈ°λ³Έμ μΈ μ¬μ© λ°©λ²μ μκ³ μΆλ€λ©΄ μμ νμ΄μ§λ₯Ό μ°Έμ‘°ν΄ μ£ΌμΈμ .
β’
μ€ν€λ§ : aloha
β’
ν
μ΄λΈ μμ±
β¦
board
board
CREATE TABLE `board` (
`no` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`writer` varchar(100) NOT NULL,
`content` text,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int NOT NULL DEFAULT '0',
PRIMARY KEY (`no`)
) COMMENT='κ²μν';
SQL
볡μ¬
λ‘μ§ μμ±
β’
DTO μμ±
β’
SQL Mapper μμ±
β’
Mapper μΈν°νμ΄μ€ μμ±
β’
Service μμ±
β’
Controller μμ±
β’
View μμ±
DTO μμ±
β’
Board.java
Board.java
Board dtoλ λ°μ΄ν°λ² μ΄μ€μ board ν
μ΄λΈκ³Ό 맀ννκΈ° μν λ°μ΄ν° μ μ‘ κ°μ²΄μ
λλ€
/**
* Board
* - κ²μκΈ μ 보
*/
@Data
public class Board {
private int no;
private String title;
private String writer;
private String content;
private Date createdAt;
private Date updatedAt;
private int views;
}
Java
볡μ¬
SQL Mapper μμ±
SQL Mapperμλ λ°μ΄ν°λ² μ΄μ€μ μμ²μ 보λ΄κΈ° μν SQL 쿼리λ€μ xml νκ·Έ νμμΌλ‘ μ μν©λλ€
β’
κΈ°λ³Έ Mapper νμΌ νμ
β’
κΈ°λ³Έ CRUD Mapper νμΌ μ½λ
β’
BoardMapper.xml
κΈ°λ³Έ Mapper νμΌ νμ
Mybatis Mapper νμΌμλ μ΅μμ νκ·Έλ‘ <mapper> νκ·Έλ₯Ό μμ±νκ³ λ€μμ€νμ΄μ€ μμ±μ μμ±ν΄μ λνΌ μΈν°νμ΄μ€μ κ²½λ‘λ₯Ό μ§μ ν©λλ€.
namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.aloha.mybatis.mapper.XXXMapper">
</mapper>
XML
볡μ¬
κΈ°λ³Έ CRUD Mapper νμΌ μ½λ
SQL νκ·Έ
<select id="select" resultType="base">
Mapper μΈν°νμ΄μ€ λ©μλ
public Base select(int baseNo) throws Exception;
λ‘μ§μ ν΅ν΄μ Mapper μΈν°νμ΄μ€μ λ©μλκ° νΈμΆμ΄ λλ©΄, μ΄μ 맀νλμ΄ μλ SQL mapper νμΌμ ν΄λΉ λ©μλλͺ
κ³Ό μΌμΉνλ μμ΄λλ₯Ό κ°μ§ SQL νκ·Έκ° μ€νλ©λλ€
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.aloha.mybatis.mapper.BaseMapper">
<!-- κΈ°λ³Έ λ±λ‘ -->
<insert id="insert">
INSERT INTO base( base_id, base_name )
VALUES ( #{baseId}, #{baseName} )
</insert>
<!-- κΈ°λ³Έ μ‘°ν -->
<select id="select" resultType="base">
SELECT *
FROM base
WHERE base_no = #{baseNo}
</select>
<!-- κΈ°λ³Έ μμ -->
<update id="update">
UPDATE base
SET base_id = #{baseId}
,base_name = #{baseName}
WHERE base_no = #{baseNo}
</update>
<!-- κΈ°λ³Έ μμ -->
<delete id="delete">
DELETE FROM base
WHERE base_no = #{baseNo}
</delete>
</mapper>
XML
볡μ¬
BoardMapper.xml
μ΄λ² μ€μ΅μμλ κ²μκΈ λ°μ΄ν°λ₯Ό κΈ°λ³Έμ μΌλ‘ λ±λ‘ μ‘°ν μμ μμ νλ 쿼리λ€μ λ€μκ³Ό κ°μ΄ SQL νκ·Έλ‘ μμ±ν΄ λ΄
λλ€.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.aloha.mybatis.mapper.BoardMapper">
<!-- κ²μκΈ λͺ©λ‘ -->
<select id="list" resultType="Board">
SELECT *
FROM board
ORDER BY created_at DESC
</select>
<!-- κ²μκΈ μ‘°ν -->
<select id="select" resultType="Board">
SELECT *
FROM board
WHERE no = #{no}
</select>
<!-- κ²μκΈ λ±λ‘ -->
<insert id="insert">
INSERT INTO board( title, writer, content)
VALUES ( #{title}, #{writer}, #{content} )
</insert>
<!-- κ²μκΈ μμ -->
<update id="update">
UPDATE board
SET title = #{title}
,writer = #{writer}
,content = #{content}
WHERE no = #{no}
</update>
<!-- κ²μκΈ μμ -->
<delete id="delete">
DELETE FROM board
WHERE no = #{no}
</delete>
<!-- κ²μκΈ λ²νΈ μ΅λκ° -->
<select id="maxPk" resultType="int">
SELECT MAX(no)
FROM board
</select>
</mapper>
XML
볡μ¬
Mapper μΈν°νμ΄μ€ μμ±
λ§μ΄λ°ν°μ€ λ§€νΌ μΈν°νμ΄μ€μ λ©μλλͺ
μ λ§€νΌ νμΌμ id μμ±κ°κ³Ό μΌμΉν΄μΌνλ€.
- ν΄λΉ λ©μλκ° νΈμΆλλ©΄, λ§€νΌ XML νμΌμ SQLλ₯Ό μ€ννλ€.
β’
BoardMapper.java
BoardMapper.java
@Mapper
public interface BoardMapper {
// κ²μκΈ λͺ©λ‘
public List<Board> list() throws Exception;
// κ²μκΈ μ‘°ν
public Board select(int no) throws Exception;
// κ²μκΈ λ±λ‘
public int insert(Board board) throws Exception;
// κ²μκΈ μμ
public int update(Board board) throws Exception;
// κ²μκΈ μμ
public int delete(int no) throws Exception;
// κ²μκΈ λ²νΈ(κΈ°λ³Έν€) μ΅λκ°
public int maxPk() throws Exception;
}
Java
볡μ¬
λ§€νΌ νμΌμ idμ μΌμΉνλ λ©μλλͺ
μ μμ±νκ³ , λ§€νΌ νμΌμ SQL νκ·Έμ μ λ¬ν΄ μ€ νλΌλ―Έν°λ€μ 맀κ°λ³μλ‘ μμ±ν©λλ€.
λν μ‘°ν 쿼리μ κ²½μ°μλ μ‘°ν κ²°κ³Όλ₯Ό 맀ν λ°μ κ°μ²΄ νΉμ 컬λ μ
μ λ°ν νμ
μΌλ‘ μμ±νκ³ , λ±λ‘, μμ , μμ , 쿼리μ κ²½μ°μλ λ°μ΄ν°λ² μ΄μ€μμ μ²λ¦¬λ νμ μλ₯Ό λ°νλ°κΈ° μνμ¬ int νμ
μΌλ‘ μμ±ν©λλ€
Service μμ±
μ΄μ μλΉμ€ μΈν°νμ΄μ€μ ꡬν ν΄λμ€λ₯Ό μμ±ν©λλ€.
β’
BoardService.java
β’
BoardServiceImpl.java
BoardService.java
μλΉμ€ μΈν°νμ΄μ€λ₯Ό ν΅ν΄μ λΉμ¦λμ€ λ‘μ§μμ μ¬μ©ν κΈ°λ₯μ λν λ©μλμ ννλ₯Ό μ μν©λλ€. μ΄λ κ² μΈν°νμ΄μ€λ‘ λ©μλ ννλ₯Ό μ μν¨μΌλ‘μ¨, μ€μ λ‘ κ΅¬νν μ½λμ λν΄μ λ€νμ±κ³Ό νμ₯μ±μ μ 곡ν©λλ€.
public interface BoardService {
// κ²μκΈ λͺ©λ‘
public List<Board> list() throws Exception;
// κ²μκΈ μ‘°ν
public Board select(int no) throws Exception;
// κ²μκΈ λ±λ‘
public int insert(Board board) throws Exception;
// κ²μκΈ μμ
public int update(Board board) throws Exception;
// κ²μκΈ μμ
public int delete(int no) throws Exception;
}
Java
볡μ¬
BoardServiceImpl.java
ꡬν ν΄λμ€μμλ λ§€νΌ μΈν°νμ΄μ€μ μ μ ν λ©μλλ‘ νΈμΆν¨μΌλ‘μ¨ λ°μ΄ν°μ λνμ¬ μ‘°ν, λ±λ‘, μμ , μμ μμ²μ λ³΄λΌ μ μλλ‘ μ½λλ₯Ό μμ±ν©λλ€. λν κ° λ©μλμμλ μλΉμ€μ κ° κΈ°λ₯μ λν μΆκ° λ‘μ§μ νμ₯νκ±°λ κ΄λ ¨λ λ‘κ·Έ λ° μ²λ¦¬λ€μ ν μ μμ΅λλ€.
@Service // μλΉμ€ μν μ μ€νλ§ λΉ
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
/**
* κ²μκΈ λͺ©λ‘ μ‘°ν
*/
@Override
public List<Board> list() throws Exception {
// TODO : boardMapper λ‘ list() νΈμΆ
/*
* β‘ List<Board> boardList λ‘ λ°μμ΄
* β‘ return boardList
*/
List<Board> boardList = boardMapper.list();
return boardList;
}
/**
* κ²μκΈ μ‘°ν
* - no 맀κ°λ³μλ‘ κ²μκΈ λ²νΈλ₯Ό μ λ¬λ°μμ
* λ°μ΄ν°λ² μ΄μ€μ μ‘°ν μμ²
*/
@Override
public Board select(int no) throws Exception {
// TODO : boardMapper λ‘ select(no) νΈμΆ
/*
* β‘ Board board λ‘ λ°μμ΄
* β‘ return board
*/
Board board = boardMapper.select(no);
return board;
}
/**
* κ²μκΈ λ±λ‘
*/
@Override
public int insert(Board board) throws Exception {
// TODO : boardMapper λ‘ insert(Board) νΈμΆ
/*
* β‘ int result λ‘ λ°μ΄ν° μ²λ¦¬ ν(κ°μ) λ°μμ΄
* β‘ return result
*/
int result = boardMapper.insert(board);
return result;
}
/**
* κ²μκΈ μμ
*/
@Override
public int update(Board board) throws Exception {
// TODO : boardMapper λ‘ update(Board) νΈμΆ
/*
* β‘ int result λ‘ λ°μ΄ν° μ²λ¦¬ ν(κ°μ) λ°μμ΄
* β‘ return result
*/
int result = boardMapper.update(board);
return result;
}
/**
* κ²μκΈ μμ
*/
@Override
public int delete(int no) throws Exception {
// TODO : boardMapper λ‘ delete(no) νΈμΆ
/*
* β‘ int result λ‘ λ°μ΄ν° μ²λ¦¬ ν(κ°μ) λ°μμ΄
* β‘ return result
*/
int result = boardMapper.delete(no);
return result;
}
}
Java
볡μ¬
Controller μμ±
컨νΈλ‘€λ¬μμλ μμ² κ²½λ‘λ₯Ό 맀ννμ¬ ν΄λΌμ΄μΈνΈμ μμ²μ λνμ¬ μ μ ν μλΉμ€ λ‘μ§ λ° λ°μ΄ν°λ₯Ό μ²λ¦¬νκ³ , ν΄λΌμ΄μΈνΈμκ² μλ΅ν λ·° νμ΄μ§λ₯Ό μ§μ ν©λλ€.
BoardController.java
package com.aloha.mybatis.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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.aloha.springmybatis.dto.Board;
import com.aloha.springmybatis.service.BoardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
/**
* /board κ²½λ‘λ‘ μμ² μμ λ μ²λ¦¬
* [GET] - /board/list : κ²μκΈ λͺ©λ‘ νλ©΄
* [GET] - /board/read : κ²μκΈ μ‘°ν νλ©΄
* [GET] - /board/insert : κ²μκΈ λ±λ‘ νλ©΄
* [POST] - /board/insert : κ²μκΈ λ±λ‘ μ²λ¦¬
* [GET] - /board/update : κ²μκΈ μμ νλ©΄
* [POST] - /board/update : κ²μκΈ μμ μ²λ¦¬
* [POST] - /board/delete : κ²μκΈ μμ μ²λ¦¬
*/
@Slf4j // λ‘κ·Έ μ΄λ
Έν
μ΄μ
@Controller // 컨νΈλ‘€λ¬ μ€νλ§ λΉμΌλ‘ λ±λ‘
@RequestMapping("/board") // ν΄λ μ€ λ 벨 μμ² κ²½λ‘ λ§€ν
// - /board/~ κ²½λ‘μ μμ²μ μ΄ μ»¨νΈλ‘€λ¬μμ μ²λ¦¬
public class BoardController {
// βλ°μ΄ν° μμ²κ³Ό νλ©΄ μΆλ ₯
// Controller --> Service (λ°μ΄ν° μμ²)
// Controller <-- Service (λ°μ΄ν° μ λ¬)
// Controller --> Model (λͺ¨λΈ λ±λ‘)
// View <-- Model (λ°μ΄ν° μΆλ ₯)
@Autowired // μμ‘΄μ± μλ μ£Όμ
private BoardService boardService; // @Serviceλ₯Ό --Impl μ λ±λ‘
/**
* κ²μκΈ λͺ©λ‘ μ‘°ν νλ©΄
* @return
* @throws Exception
*/
@GetMapping("/list")
public String list(Model model) throws Exception {
// λ°μ΄ν° μμ²
List<Board> boardList = boardService.list();
// λͺ¨λΈ λ±λ‘
model.addAttribute("boardList", boardList);
// λ·° νμ΄μ§ μ§μ
return "/board/list"; // resources/templates/board/list.html
}
/**
* κ²μκΈ μ‘°ν νλ©΄
* - /board/read?no=π
* @param no
* @return
* @throws Exception
*/
// @RequestParam("νλΌλ―Έν°λͺ
")
// - μ€νλ§ λΆνΈ 3.2λ²μ μ΄ν, μλ΅ν΄λ μλ 맀νλλ€.
// - μ€νλ§ λΆνΈ 3.2λ²μ μ΄μ, νμλ‘ λͺ
μν΄μΌ 맀νλλ€.
@GetMapping("/read")
public String read(@RequestParam("no") int no, Model model) throws Exception {
// λ°μ΄ν° μμ²
Board board = boardService.select(no);
// λͺ¨λΈ λ±λ‘
model.addAttribute("board", board);
// λ·°νμ΄μ§ μ§μ
return "/board/read";
}
/**
* κ²μκΈ λ±λ‘ νλ©΄
* @return
*/
@GetMapping("/insert")
public String insert() {
return "/board/insert";
}
/**
* κ²μκΈ λ±λ‘ μ²λ¦¬
* @param board
* @return
* @throws Exception
*/
@PostMapping("/insert")
public String insertPro(Board board) throws Exception {
// λ°μ΄ν° μμ²
int result = boardService.insert(board);
// 리λ€μ΄λ νΈ
// β λ°μ΄ν° μ²λ¦¬ μ±κ³΅
if( result > 0 ) {
return "redirect:/board/list";
}
// β λ°μ΄ν° μ²λ¦¬ μ€ν¨
return "redirect:/board/insert?error";
}
/**
* κ²μκΈ μμ νλ©΄
* @param no
* @param model
* @return
* @throws Exception
*/
@GetMapping("/update")
public String update(@RequestParam("no") int no, Model model) throws Exception {
Board board = boardService.select(no);
model.addAttribute("board", board);
return "/board/update";
}
/**
* κ²μκΈ μμ μ²λ¦¬
* @param board
* @return
* @throws Exception
*/
@PostMapping("/update")
public String updatePro(Board board) throws Exception {
int result = boardService.update(board);
if( result > 0 ) {
return "redirect:/board/list";
}
int no = board.getNo();
return "redirect:/board/update?no="+ no + "&error";
}
/**
* κ²μκΈ μμ μ²λ¦¬
* @param no
* @return
* @throws Exception
*/
@PostMapping("/delete")
public String delete(@RequestParam("no") int no) throws Exception {
int result = boardService.delete(no);
if( result > 0 ) {
return "redirect:/board/list";
}
return "redirect:/board/update?no=" + no + "&error";
}
}
Java
볡μ¬
View μμ±
β’
board
β¦
list.html
β¦
insert.html
β¦
read.html
β¦
update.html
β’
index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>λ©μΈ νλ©΄</title>
</head>
<body>
<h1>SpringBoot x MyBatis</h1>
<h3>κ²μν νλ‘μ νΈ</h3>
<ul>
<li>Spring Boot 3.x</li>
<li>Thymeleaf</li>
<li>MySQL 8.x</li>
<li>MyBatis 3.0</li>
</ul>
<div>
<a href="/board/list">κ²μν</a>
</div>
</body>
</html>
HTML
볡μ¬
β’
board
list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>κ²μκΈ λͺ©λ‘</title>
</head>
<body>
<h1>κ²μκΈ λͺ©λ‘</h1>
<a href="/board/insert">κΈμ°κΈ°</a>
<table border="1">
<tr>
<th width="50">λ²νΈ</th>
<th width="300">μ λͺ©</th>
<th width="100">μμ±μ</th>
<th width="200">λ±λ‘μΌμ</th>
<th width="200">μμ μΌμ</th>
<th widht="100">μ‘°νμ</th>
</tr>
<th:block th:each="board : ${boardList}">
<tr>
<td align="center" th:text="${board.no}"></td>
<td>
<!-- th:???="|λ¬Έμμ΄+${ννμ}|" -->
<a th:href="|/board/read?no=${board.no}|"
th:text="${board.title}"></a>
</td>
<td align="center" th:text="${board.writer}"></td>
<!--
μ νΈλ¦¬ν°κ°μ²΄.λ©μλ()
#dates.format( λ μ§κ°μ²΄λͺ
, 'λ μ§ν¬λ§·' )
- #dates.format( board.regDate, 'yyyy-MM-dd HH:mm:ss' )
-->
<td align="center">
<span th:text="${ #dates.format( board.createdAt, 'yyyy-MM-dd HH:mm:ss' ) }"></span>
</td>
<td align="center">
<span th:text="${ #dates.format( board.updatedAt, 'yyyy-MM-dd HH:mm:ss' ) }"></span>
</td>
<td align="center" th:text="${board.views}"></td>
</tr>
</th:block>
</table>
</body>
</html>
HTML
볡μ¬
insert.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>κ²μκΈ λ±λ‘</title>
</head>
<body>
<h1>κ²μκΈ λ±λ‘</h1>
<form action="/board/insert" method="post">
<input type="text" name="title" id="title">
<input type="text" name="writer" id="writer">
<input type="text" name="content" id="content">
<input type="submit" value="λ±λ‘">
</form>
</body>
</html>
HTML
볡μ¬
read.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>κ²μκΈ μ‘°ν</title>
</head>
<body>
<h1>κ²μκΈ μ‘°ν</h1>
<form action="/board/delete" method="post">
<input type="hidden" name="no" th:value="${board.no}">
<table>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" name="title" th:value="${board.title}">
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" name="writer" th:value="${board.writer}">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" id="content" cols="40" rows="5"
th:text="${board.content}"></textarea>
</td>
</tr>
</table>
<div>
<button type="button" onclick="moveUpdate()">μμ </button>
<button type="button" onclick="moveList()">λͺ©λ‘</button>
</div>
</form>
<script>
// π©βπ» λͺ¨λΈ κ°μ²΄λ₯Ό μλ°μ€ν¬λ¦½νΈλ‘ κ°μ Έμ€λ λ°©λ²
let no = "[[${board.no}]]"
// μμ νλ©΄ μ΄λ
function moveUpdate() {
location.href = '/board/update?no=' + no
}
// λͺ©λ‘ νλ©΄ μ΄λ
function moveList() {
location.href = '/board/list'
}
</script>
</body>
</html>
HTML
볡μ¬
update.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>κ²μκΈ μμ </title>
</head>
<body>
<h1>κ²μκΈ μμ </h1>
<form id="form" action="/board/update" method="post">
<input type="hidden" name="no" th:value="${board.no}">
<table>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" name="title" th:value="${board.title}">
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" name="writer" th:value="${board.writer}">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="content" id="content" cols="40" rows="5"
th:text="${board.content}"></textarea>
</td>
</tr>
</table>
<div>
<button type="submit">μμ </button>
<button type="button" onclick="actionDelete()">μμ </button>
<button type="button" onclick="moveList()">λͺ©λ‘</button>
</div>
</form>
<script>
let form = document.getElementById('form')
// π©βπ» λͺ¨λΈ κ°μ²΄λ₯Ό μλ°μ€ν¬λ¦½νΈλ‘ κ°μ Έμ€λ λ°©λ²
let no = "[[${board.no}]]"
// μμ νλ©΄ μ΄λ
function moveUpdate() {
location.href = '/board/update?no=' + no
}
// μμ μμ²
function actionDelete() {
let check = confirm('μ λ§λ‘ μμ νμκ² μ΅λκΉ?')
if( check ) {
form.action = '/board/delete'
form.submit()
}
}
// λͺ©λ‘ νλ©΄ μ΄λ
function moveList() {
location.href = '/board/list'
}
</script>
</body>
</html>
HTML
볡μ¬
κΈ°λ₯ λͺ
μΈμ
β’
κ²μκΈ λ±λ‘
β’
κ²μκΈ λͺ©λ‘ μ‘°ν
β’
κ²μκΈ μ‘°ν
β’
κ²μκΈ μμ
β’
κ²μκΈ μμ
κ²μκΈ λ±λ‘
κ²μκΈ λ±λ‘ μ, μ¬μ©μκ° /board/insert.html μμ κ²μκΈ μ 보 (μ λͺ©, μμ±μ, λ΄μ©)λ₯Ό μ
λ ₯νκ³ , μ¬λ¬ νμΌμ 첨λΆνμ¬ μμ²νλ€.
β’
κ²μκΈ μ 보 λ±λ‘
β’
νμΌ μ
λ‘λ
κ²μκΈ μ 보 λ±λ‘
β’
Model
β¦
BoardService.java
βͺ
insert(Board)
β¦
BoardServiceImpl.java
βͺ
insert(Board)
β’
κ²μκΈ μ 보 λ±λ‘
β¦
BoardMapper μ insert(Board) νΈμΆ
β’
νμΌ μ
λ‘λ
β¦
FileService μ upload(List<Files>) νΈμΆ
β¦
BoardMapper.java
βͺ
insert(Board)
β’
BoardMapper.xml μ id=βinsertβ 쿼리μ μ°κ²°
β¦
BoardMapper.xml
βͺ
<insert id=βinsertβ β¦ >
β’
μ μ©λ λ°μ΄ν° νμ μλ₯Ό λ°ν ( 0 λλ 1 )
β’
View
β¦
~/board/insert.html
βͺ
[POST] λ°©μμΌλ‘ FORM μμ²
β’
νλΌλ―Έν°
β¦
μ λͺ© : title
β¦
μμ±μ : writer
β¦
λ΄μ© : content
β¦
νμΌ : file
β’
Controller
β¦
BoardController.java
βͺ
@GetMapping(β/board/insertβ)
β’
μλ΅
β¦
/board/insert
βͺ
@PostMapping(β/board/insertβ)
β’
@RequestBody Board board
β’
BoardService μ insert() λ©μλ μμ²
β’
μλ΅
β¦
β¦
κ²μκΈ λͺ©λ‘ μ‘°ν
κ²μκΈ μ μ 체 λͺ©λ‘μ μ‘°νν©λλ€.
β’
κ²μκΈ λͺ©λ‘ μ 체 μ‘°ν
κ²μκΈ λͺ©λ‘ - MVC
β’
Model : BoardService
β’
View : /board/list.html
β’
Controller : BoardController.java
κ²μκΈ λͺ©λ‘ μ‘°ν
β’
Model
β¦
BoardService.java
βͺ
list()
β¦
BoardServiceImpl.java
βͺ
list()
β¦
BoardMapper.java
βͺ
list()
β’
BoardMapper.xml μ id=βlistβ 쿼리μ μ°κ²°
β¦
BoardMapper.xml
βͺ
<seledct id=βlistβ resultType=βBoardβ β¦ >
β’
resultType=βBoardβ
β¦
μ‘°νλ board ν
μ΄λΈμ Board κ°μ²΄λ‘ 맀ν
β’
View
β¦
~/board/list.html
β’
Controller
β¦
BoardController.java
βͺ
@GetMapping(β/board/listβ)
β’
Model
boardList
β’
μλ΅
β¦
/board/list
κ²μκΈ μ‘°ν
κ²μκΈ μ 보 ν 건μ μ‘°νν©λλ€.
β’
κ²μκΈ μ 보 μ‘°ν
β’
μ²¨λΆ νμΌ λͺ©λ‘ μ‘°ν
κ²μκΈ μ 보 μ‘°ν
β’
Model
β¦
BoardService.java
βͺ
select(no)
β¦
BoardServiceImpl.java
βͺ
select(no)
β¦
BoardMapper.java
βͺ
select(no)
β’
BoardMapper.xml μ id=βselectβ 쿼리μ μ°κ²°
β¦
BoardMapper.xml
βͺ
<seledct id=βselectβ resultType=βBoardβ β¦ >
β’
resultType=βBoardβ
β¦
μ‘°νλ board ν
μ΄λΈμ Board κ°μ²΄λ‘ 맀ν
β’
View
β¦
~/board/read.html
β’
Controller
β¦
BoardController.java
βͺ
@GetMapping(β/board/readβ)
β’
Model
board
β’
μλ΅
β¦
/board/read
κ²μκΈ μμ
κ²μκΈ μ 보 ν 건μ μμ ν©λλ€.
β’
κ²μκΈ μ 보 μμ
β’
νμΌ μμ (AJAX)
κ²μκΈ μ 보 μμ
β’
Model
β¦
BoardService.java
βͺ
update(board)
β¦
BoardServiceImpl.java
βͺ
update(board)
β¦
BoardMapper.java
βͺ
update(board)
β’
BoardMapper.xml μ id=βupdateβ 쿼리μ μ°κ²°
β¦
BoardMapper.xml
βͺ
<update id=βupdateβ β¦ >
β’
μ μ©λ λ°μ΄ν° νμ μλ₯Ό λ°ν ( 0 λλ 1 )
β’
View
β¦
~/board/update.html
β’
Controller
β¦
BoardController.java
βͺ
@GetMapping(β/board/updateβ)
β’
Model
board
β’
μλ΅
β¦
/board/update
βͺ
@PostMapping(β/board/updateβ)
β’
@RequestBody Board board
β’
BoardService μ update() λ©μλ μμ²
β’
μλ΅
β¦
β¦
κ²μκΈ μμ
κ²μκΈ μ 보 ν 건μ μμ ν©λλ€.
β’
κ²μκΈ μμ
β’
μ²¨λΆ νμΌ μμ
κ²μκΈ μμ
β’
Model
β¦
BoardService.java
βͺ
delete(no)
β¦
BoardServiceImpl.java
βͺ
delete(no)
β¦
BoardMapper.java
βͺ
delete(no)
β’
BoardMapper.xml μ id=βdeleteβ 쿼리μ μ°κ²°
β¦
BoardMapper.xml
βͺ
<delete id=βdeleteβ β¦ >
β’
μ μ©λ λ°μ΄ν° νμ μλ₯Ό λ°ν ( 0 λλ 1 )
β’
View
β¦
~/board/update.html μμ [μμ ] λ²νΌμΌλ‘ μμ²
β’
Controller
β¦
BoardController.java
βͺ
@GetMapping
β’
βͺ
@PostMapping(β/board/deleteβ)
β’
@RequestBody Board board
β’
BoardService μ delete() λ©μλ μμ²
β’
μλ΅
β¦
β¦