Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자 도전기

[Spring] MyBatis란? 본문

개발공부/Spring

[Spring] MyBatis란?

jnnjnn 2024. 4. 29. 21:02

 

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>