MyBatis : DB ์ก์ธ์ค๋ฅผ ์ํ ์๋ฐ ORM ํ๋ ์์ํฌ์
๋๋ค. SQL ์ฟผ๋ฆฌ์ ์๋ฐ ๊ฐ์ฒด๋ฅผ ์๋์ผ๋ก ๋งคํํ๋ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Mapper02 ์ธํฐํ์ด์ค
@Mapper
public interface Mapper02 {
@Select("SELECT * FROM Customers WHERE CustomerID = 1")
MyBean254Customer selectOneCustomer2();
@Select("""
SELECT CustomerId id, CustomerName name,
ContactName, Address, City, Country, PostalCode
FROM Customers WHERE CustomerID = 1""")
MyBean254Customer selectOneCustomer3();
}
@Mapper ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ MyBatis mapper ์ธํฐํ์ด์ค๋ก ์ง์ ๋์์ต๋๋ค.@Mapper๊ฐ ๋ถ์ ์ธํฐํ์ด์ค์ ๋ํด ์๋์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.Controller31.java
@Controller
@RequestMapping("main31")
@RequiredArgsConstructor
public class Controller31 {
private final Mapper02 mapper; //Mapper ์ธํฐํ์ด์ค ์์ฑ์ ์ฃผ์
@GetMapping("sub3")
public void method3(){
MyBean254Customer c = mapper.selectOneCustomer2();
System.out.println("c = " + c);
}
@GetMapping("sub4")
public void method4(){
MyBean254Customer c = mapper.selectOneCustomer3();
System.out.println("c = " + c);
}
}
selectOneCustomer2()์ ๊ฒฐ๊ณผ๊ฐ์ c = MyBean254Customer(id=0, name=null, contactName=Maria Anders, address=Obere Str. 57, city=Berlin, country=๋
์ผ, postalCode=12209) ์ด๋ฉฐ id, name์ด ์ปฌ๋ผ๋ช
๊ณผ ํ๋กํผํฐ๋ช
์ด ๊ฐ์ง ์์ ๊ฐ์ด ๋์ค์ง ์์ต๋๋ค.
selectOneCustomer3()์ ๊ฒฐ๊ณผ๊ฐ์ c = MyBean254Customer(id=1, name=Alfreds Futterkiste, contactName=Maria Anders, address=Obere Str. 57, city=Berlin, country=๋
์ผ, postalCode=12209)์ด๋ฉฐ SQL ์ฟผ๋ฆฌ์์ ๋ณ์นญ์ ์ฌ์ฉํ์ฌ ์ปฌ๋ผ๋ช
์ ํ๋กํผํฐ๋ช
๊ณผ ๊ฐ๊ฒ ๋ณ๊ฒฝํด์ฃผ์ด์ ๋ชจ๋ ๊ฐ์ด ๋์ค๊ฒ ํฉ๋๋ค.
๐ฆ ๋์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ
#{} ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ SQL ์ฟผ๋ฆฌ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ธ๋ฉํฉ๋๋ค. ์ด ๋ #{} ์์ ์ ํ ์ด๋ฆ์ ๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค. @Mapper
public interface Mapper02 {
@Select("""
SELECT CustomerID id,
CustomerName name,
ContactName, Address, City, Country, PostalCode
FROM Customers
WHERE Country = #{country1} OR Country = #{country2}
ORDER BY Country
""")
List<MyBean254Customer> selectCustomersByCountry(String country1, String country2);
}
selectCustomersByCountry ๋ฉ์๋์ ๋งค๊ฐ๋ณ์์ธ country1๊ณผ country2๋ SQL ์ฟผ๋ฆฌ์ ํ๋ผ๋ฏธํฐ์ธ #{country1}๊ณผ #{country2}์ ์ด๋ฆ์ด ์ผ์นํด์ผ ํฉ๋๋ค.Controller31.java
@Controller
@RequestMapping("main31")
@RequiredArgsConstructor
public class Controller31 {
private final Mapper03 mapper;
@GetMapping("sub11")
public void method11(){
List<MyBean254Customer> list = mapper.selectCustomersByCountry("usa","uk");
list.forEach(System.out::println);
}
}
selectCustomersByCountry() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฏธ๊ตญ(USA)๊ณผ ์๊ตญ(UK)์ ํด๋นํ๋ ๊ณ ๊ฐ์ ๋ฆฌ์คํธ์ ์ ์ฅํ๊ณ , ๊ทธ ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.Mapper02 ์ธํฐํ์ด์ค
@Mapper
public interface Mapper02 {
@Delete("""
DELETE FROM Customers WHERE CustomerId = #{id}
""")
int deleteOneCustomerByID(int id);
}
Controller31.java
@Controller
@RequestMapping("main32")
@RequiredArgsConstructor
public class Controller32 {
@GetMapping("sub2")
public void method2(Integer cid){
int rowCount = mapper.deleteOneCustomerByID(cid);
System.out.println(rowCount + "๋ช
๊ณ ๊ฐ ์ญ์ ๋จ");
}
}
cid ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์์์ ํด๋น ID์ ํด๋นํ๋ ๊ณ ๊ฐ์ ์ญ์ ํฉ๋๋ค.Mapper02 ์ธํฐํ์ด์ค
@Mapper
public interface Mapper02 {
@Insert("""
INSERT INTO Customers(CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES (#{name}, #{contactName}, #{address}, #{city}, #{postalCode}, #{country})
""")
int insertCustomer(MyBean254Customer customer);
}
MyBean254Customer ๊ฐ์ฒด์ ํ๋กํผํฐ์ ์ง์ ์ ๊ทผํ์ฌ ๊ฐ์ ๋ฐ์ธ๋ฉํฉ๋๋ค.Controller32.java
@Controller
@RequestMapping("main32")
@RequiredArgsConstructor
public class Controller32 {
private final Mapper03 mapper;
@GetMapping("sub5")
public void method5(){
// form์ด ์๋ view ํฌ์๋ฉ
}
@PostMapping("sub5")
public String method6(MyBean258Employee employee, RedirectAttributes redirectAttributes){
int rowCount = mapper.insertEmployee(employee);
if (rowCount>0){
redirectAttributes.addFlashAttribute("message", rowCount+"๋ช
์ง์์ด ๋ฑ๋ก๋์์ต๋๋ค.");
}else{
redirectAttributes.addFlashAttribute("message", "๋ฑ๋ก๋์ง ์์์ต๋๋ค");
}
return "redirect:/main32/sub5";
}
}
mapper.insertEmployee(employee); ์ผ๋ก ์ธํด ์ง์ ๋ฑ๋ก ์ฌ๋ถ์ ๋ฐ๋ฅธ ๋ฉ์์ง๋ฅผ ํ์ํฉ๋๋ค.sub5.jsp(view)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:if test="${not empty message}">
${message}
</c:if>
<h3>์ง์ ์
๋ ฅ</h3>
<hr>
<div>
<form method="post">
<div>
lastName <input type="text" name="lastName">
</div>
<div>
firstName <input type="text" name="firstName">
</div>
<div>
์์ผ <input type="date" name="birthDate">
</div>
<div>
photo <input type="file" name="photo">
</div>
<div>
๋
ธํธ :
<textarea rows="10" cols="30" name="notes"></textarea>
</div>
<div>
<input type="submit" value="๋ฑ๋ก">
</div>
</form>
</div>
</body>
</html>
๊ฒฐ๊ณผ View

๋ฐ์ดํฐ ์ฝ์

@Options(useGeneratedKeys = true, keyProperty = "id") ์ด๋
ธํ
์ด์
์ MyBatis์์ ์ฌ์ฉ๋๋ ๊ฒ์ผ๋ก, ์ฃผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ ์ฆ๊ฐ(primary key) ํ๋์ ๋ํ ์ค์ ์ ์ง์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
useGeneratedKeys = true: ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋์ผ๋ก ์์ฑํ๋ ํค๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ง์ ํฉ๋๋ค. ์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ก์ด ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ ๋ ํด๋น ํค๋ฅผ ์๋์ผ๋ก ์์ฑํ๋๋ก ํฉ๋๋ค.keyProperty = "id": ์๋ ์์ฑ๋ ํค๋ฅผ ๋งคํํ ์๋ฐ ๊ฐ์ฒด์ ์์ฑ์ ์ง์ ํฉ๋๋ค. ์ฌ๊ธฐ์ "id"๋ ์๋ ์์ฑ๋ ํค๋ฅผ ๋ฐ์๋ค์ผ ๊ฐ์ฒด์ ์์ฑ๋ช
์ ์๋ฏธํฉ๋๋ค. ์ด ์์ฑ์๋ ์๋ ์์ฑ๋ ํค์ ๊ฐ์ ์ ์ฅํฉ๋๋ค.์๋ฅผ ๋ค์ด, ๋ค์์ MyBatis XML ๋งคํผ ํ์ผ์์ @Options ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ ์๋ ์์ฑ๋ ํค๋ฅผ ์ค์ ํ๋ ์์์
๋๋ค:
@Insert("""
INSERT INTO Customers(CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES (#{name}, #{contactName}, #{address}, #{city}, #{postalCode}, #{country})
""")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertCustomer(MyBean254Customer customer);
useGeneratedKeys="true"๋ฅผ ์ค์ ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์๋ ์์ฑ๋ ํค๋ฅผ ์ฌ์ฉํ๋๋ก ์ง์ ํ๊ณ , keyProperty="id"๋ฅผ ์ค์ ํ์ฌ ํด๋น ํค๋ฅผ User ๊ฐ์ฒด์ id ์์ฑ์ ๋งคํํ๊ณ ์์ต๋๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ MyBatis๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์๋ ์์ฑ๋ ํค๋ฅผ User ๊ฐ์ฒด์ ์๋์ผ๋ก ํ ๋นํ ๊ฒ์
๋๋ค.
Mapper ์ธํฐํ์ด์ค
@Mapper
public interface Mapper02 {
@Select("""
SELECT EmployeeID id,
FirstName,
LastName,
Notes,
Photo,
BirthDate
FROM Employees
WHERE EmployeeID = #{id}
""")
MyBean258Employee selectOneEmployee2(Integer id);
}
@Mapper
public interface Mapper03 {
@Update("""
UPDATE Employees
SET LastName = #{lastName}, FirstName = #{firstName},
BirthDate = #{birthDate}, Photo = #{photo}, Notes = #{notes}
WHERE EmployeeId = #{id}
""")
int updateEmployee(MyBean258Employee employee);
}
Controller32.java
@Controller
@RequestMapping("main32")
@RequiredArgsConstructor
public class Controller32 {
private final Mapper03 mapper;
private final Mapper02 mapper02;
@GetMapping("sub6")
public void method7(@RequestParam(value = "id", required = false) Integer eid, Model model){
if(eid != null){
MyBean258Employee e = mapper02.selectOneEmployee2(eid);
model.addAttribute("employee", e);
}
}
@PostMapping("sub6/update")
public String method8(MyBean258Employee employee, RedirectAttributes redirectAttributes){
int rowCount = mapper.updateEmployee(employee);
if (rowCount>0){
redirectAttributes.addFlashAttribute("message", rowCount+"๋ช
์ง์์ด ์์ ๋์์ต๋๋ค.");
}else{
redirectAttributes.addFlashAttribute("message", "์์ ๋์ง ์์์ต๋๋ค");
}
redirectAttributes.addAttribute("id", employee.getId());
return "redirect:/main32/sub6";
}
}
redirectAttributes.addAttribute("id", employee.getId()); : ์์ ๋ ์ง์ ์์ด๋๋ฅผ ๋ค์ ์กฐํ ํ์ด์ง๋ก ์ ๋ฌํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค. redirectAttributes ๊ฐ์ฒด์ addAttribute() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ id๋ผ๋ ์ด๋ฆ์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ์ employee.getId()๋ก๋ถํฐ ์ป์ ์ง์์ ์์ด๋๋ฅผ ์ ๋ฌํ๋ฉด ๋ฆฌ๋ค์ด๋ ํธ๋ URL์ id ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋์ด ์ง์์ ์์ด๋๊ฐ ํฌํจ๋ URL์ด ์์ฑ๋ฉ๋๋ค.sub6.jsp(view)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>์ง์ ์กฐํ ๋ฐ ์์ </h3>
<c:if test="${not empty message}">
${message}
</c:if>
<form>
๋ฒํธ
<input type="number" name="id">
<button>์กฐํ</button>
</form>
<hr>
<c:if test="${empty employee}">
์กฐํ๋ ์ง์์ด ์์ต๋๋ค.
</c:if>
<c:if test="${not empty employee}">
<h3>${employee.id}๋ฒ ์ง์</h3>
<form action="/main32/sub6/update" method="post">
<div>last name
<input type="text" value="${employee.lastName}" name="lastName"></div>
<div>first name
<input type="text" value="${employee.firstName}" name="firstName"></div>
<div>birth
<input type="date" value="${employee.birthDate}" name="birthDate"></div>
<div>
photo
<input type="file" value="${employee.photo}" name="photo">
</div>
<div>notes
<textarea name="notes" id="" cols="30" rows="10">${employee.notes}</textarea></div>
<div style="display: none">
<input type="text" name="id" value="${employee.id}">
</div>
<div>
<input type="submit" value="์์ ">
</div>
</form>
</c:if>
</body>
</html>
value ์์ฑ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. name ์์ฑ์ ํด๋น ๋ฐ์ดํฐ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ช
๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค. birth๋ฅผ 1968-12-08์์ 1968-12-20์ผ๋ก ์์


๐ข ํ๋กํผํฐ๋ ์๋ฐ๋น์ ์์ฑ์ ๋งํฉ๋๋ค.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyBean254Customer {
private int id;
private String name;
private String contactName;
private String address;
private String city;
private String postalCode;
private String country;
}
์๋ฐ๋น์ ํ๋กํผํฐ ๋ช
๊ณผ JSP์์ ์ฌ์ฉํ ๋์ name ์์ฑ์ ๋งค์นญ์์ผ์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด JSP์์ ํผ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋, ๊ฐ ์
๋ ฅ ํ๋์ ์ด๋ฆ์ด ํด๋น ํ๋กํผํฐ์ ์ผ์นํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ์๋ฒ ์ธก์์ ์ด๋ฌํ ์ด๋ฆ์ ํตํด ํผ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ ์ฒ๋ฆฌํ ๋ ์ ์ฉํฉ๋๋ค.
# ๊ธฐํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. # ๊ธฐํธ ๋ด์๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ง์ ํ ์ ์์ผ๋ฉฐ, ์ด๋ ๊ฐ์ฒด์ getter ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค. ๋ฐ๋ผ์ ์ฃผ์ด์ง updateCustomer ๋ฉ์๋์์๋ MyBean254Customer ๊ฐ์ฒด์ ํ๋กํผํฐ ๊ฐ์ ๊ฐ์ ธ์์ SQL ์ฟผ๋ฆฌ์ ๋ฐ์ธ๋ฉํฉ๋๋ค.