개발자 도전기
[Spring] MyBatis란? 본문
MyBatis란?
- 자바 오프젝트와 SQL 사이의 자동 매핑 기능을 지원하는 ORM(Object relational Mapping) 프레임워크입니다
- JDBC를 통해 관계형 데이터베이스에 엑세스하는 작업을 캡슐화하고 기존 JDBC의 중복작업을 간소화해줍니다
MyBatis 사용 방법
Mapper 인터페이스에 @Mapper 어노테이션을 붙입니다. Mapper 인터페이스를 통해 SQL 쿼리를 실행할 수 있습니다.
Mapper 인터페이스의 메소드에 @Select, @Delete, @Insert, @Update 등의 어노테이션을 붙여 실행할 SQL 쿼리를 입력합니다
@Mapper
public interface Mapper02 {
}
@RequiedAtgsConstructor 어노테이션으로 생성된 생성자로 컨트롤러에 Mapper 객체를 의존성 주입할 수 있습니다.
@Controller
@RequiredArgsConstructor
@RequestMapping("main31")
public class Controller31 {
private final Mapper02 mapper02;
}
값 바인딩
메소드의 리턴 타입으로 지정된 객체의 프로퍼티명과 조회 결과인 컬럼명이 같으면 값을 바인딩 해 줍니다
@Select("""
SELECT EmployeeID,
LastName,
FirstName,
Photo,
Notes,
BirthDate
FROM Employees
WHERE EmployeeID = #{id}
""")
MyBean255Employee selectOneEmployee2(Integer id);
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyBean255Employee {
private String employeeID;
private String lastName;
private String firstName;
private String birthDate;
private String photo;
private String notes;
}
컬럼명과 프로퍼티명이 다를 경우, 컬럼명에 별칭을 붙여 값을 바인딩 할 수 있습니다.
@Select("""
SELECT string_col stringCol,
int_col intCol,
dec_col decCol,
date_col dateCol,
date_time_col dateTimeCol
FROM my_table9
""")
List<MyBean331> select1();
또, application.properties에 다음과 같은 설정을 추가하면 snake case를 camel case로 바꿔줍니다
# mybatis map snake case to camel case
mybatis.configuration.map-underscore-to-camel-case=true
@Select
@Select("""
SELECT *
FROM Customers
WHERE Country = #{country1}
OR Country = #{country2}
ORDER BY Country;
""")
List<MyBean253Customer> selectCustomerByCountry(String country1, String country2);
메소드의 매개변수인 country1과 country2의 값을 받아와 해당 국가의 고객들을 조회하는 SQL 쿼리입니다.
조회된 각 고객의 정보는 MyBean253Customer 객체에 저장되어 List<MyBean253Customer>를 리턴합니다
@Delete
@Delete("""
DELETE FROM Customers
WHERE CustomerID = #{id}
""")
int deleteOneCustomerById2(Integer id);
CustomerID가 id인 고객을 삭제하는 쿼리입니다
삭제한 데이터의 수를 int로 반환합니다
@Insert
@Insert("""
INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES (#{customerName},#{contactName},#{address},#{city},#{postalCode},#{country})
""")
int insertCustomer(MyBean253Customer customer);
MyBean253Customer에 바인딩 된 값을 고객 정보로 입력하는 쿼리입니다
객체의 프로퍼티 값을 다음과 같이 입력할 수 있습니다
입력한 데이터의 수를 int로 반환합니다
@Update
@Update("""
UPDATE Employees
SET
LastName = #{lastName},
FirstName = #{firstName},
BirthDate = #{birthDate},
Photo = #{photo},
Notes = #{notes}
WHERE EmployeeID = #{employeeID}
""")
int updateEmployee(MyBean255Employee employee);
MyBean255Employee에 바인딩 된 값을 고객 정보로 수정하는 쿼리입니다
입력한 데이터의 수를 int로 반환합니다
Controller + Mapper + view로 포워딩
MyBatis를 사용하여 my_table10에 데이터를 추가하는 예제이다.
@Controller
@RequestMapping("main33")
@RequiredArgsConstructor
public class Controller33 {
@GetMapping("sub12")
public void select12(Model model) {
List<MyBean333> list = mapper.select3();
model.addAttribute("datas", list);
}
@PostMapping("sub12")
public String insert12(MyBean333 data, RedirectAttributes rttr) {
int i = mapper.insert5(data);
if (i > 0) {
rttr.addFlashAttribute("message", "등록 완료!");
} else {
rttr.addFlashAttribute("message", "등록 실패 !");
}
return "redirect:/main33/sub12";
}
}
필드의 타입은 Integer와 int 모두 바인딩이 가능하지만, Integer는 값을 지정하지 않으면 null이 저장되고 int는 값을 지정하지 않으면 기본값인 0이 저장되어 Integer 타입으로 선언하는 것을 추천합니다
@Data
public class MyBean333 {
private String title;
private String name;
private Integer age;
private Double price;
private LocalDate published;
private LocalDateTime inserted;
}
@Mapper
public interface Mapper04 {
@Select("""
SELECT *
FROM my_table10
""")
List<MyBean333> select3();
@Insert("""
INSERT INTO my_table10
(title, name, age, price, published, inserted)
VALUES (#{title}, #{name}, #{age}, #{price}, #{published}, #{inserted})
""")
int insert5(MyBean333 obj);
}
<html>
<head>
<title>Title</title>
<style>
table, tr, td, th {
border-collapse: collapse;
border: 1px solid black;
}
</style>
</head>
<body>
<c:if test="${not empty message}">
<div style="background-color: skyblue; padding: 20px">
${message}
</div>
</c:if>
<h3>직원 등록</h3>
<form action="" method="post">
<div>
<input type="text" name="title" value="제목">
</div>
<div>
<input type="text" name="name" value="이름">
</div>
<div>
<input type="number" name="age" value="100">
</div>
<div>
<input type="number" name="price" value="12.34" step="0.01">
</div>
<div>
<input type="date" name="published" value="1991-01-01">
</div>
<div>
<input type="datetime-local" name="inserted" value="1991-01-01T12:00:00">
</div>
<div>
<input type="submit" value="제출">
</div>
</form>
<hr>
<h3>직원 조회</h3>
<table>
<thead>
<tr>
<th>title</th>
<th>name</th>
<th>age</th>
<th>price</th>
<th>date</th>
<th>dateTime</th>
</tr>
</thead>
<tbody>
<c:forEach items="${datas}" var="data">
<tr>
<td>${data.title}</td>
<td>${data.name}</td>
<td>${data.age}</td>
<td>${data.price}</td>
<td>${data.published}</td>
<td>${data.inserted}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
'개발공부 > Spring' 카테고리의 다른 글
[Spring] Service로 비즈니스 로직 처리하기 (0) | 2024.05.01 |
---|---|
[SQL] 서브쿼리(Sub query) (0) | 2024.05.01 |
[Spring] IOC (제어의 역전) (0) | 2024.04.25 |
[Spring] JDBC로 데이터 수정하기 (UPDATE) (0) | 2024.04.23 |
[Spring] JDBC로 데이터 삭제하기(DELETE) (0) | 2024.04.23 |