I. Mybatis
1. 들어가며
(1) 의의
Mybatis란 SQL과 그것을 쿼리하는 Dao를 매핑하는 프레임워크이다.
Dao를 구현하지 않아도 되는 프레임워크이다. SQL만 작성하면 나머지는 알아서 해주는 프레임워크이다
(2) 준비물
1 Mybatis라이브러리 준비하기
2 구현할 Dao interface 준비하기
3 Dao interface에 SQL Mapping 하기
2. 실습
(1) Mybatis 라이브러리 준비하기- 스프링 starter 에 추가
(2) Dao 인터페이스 준비하기
1) 다음처럼 인터페이스 준비한다.
package kr.co.rland.web.repository;
import java.util.List;
import kr.co.rland.web.entity.Menu;
public interface MenuRepository {
List<Menu> findAll();
Menu findById(long id);
Menu insert(Menu menu);
Menu update(Menu menu);
void delete(long id);
}
다음과 같이 인터페이스 준비 하고, 구현하기위한 재료로 SQL 매핑하면 mybathis가 알아서 Dao구현체 마련해줌 우리는 이것을 사용해주면 됨
(3) Interface에 SQL매핑하기
이러한 매핑방법으로 두가지가 있다. 고전적인 XML방식과 최근 Annotation방식이 있다
다만 이경우 annotation 방식보다 XML방식이 선호된다
(4) Annotation 방식
XML방식이 선호되는 이유를 Annotation방식으로 살펴보면서 그 한계점을 살펴보면 알수있다.
package kr.co.rland.web.repository;
import java.util.List;
//ibatis가 원래 이름이야!
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import kr.co.rland.web.entity.Menu;
//이것을 구현한 구현체를 알아서 repo에 보내주는거야!
@Mapper
public interface MenuRepository {
//jdbc 와 mybatis로 구현한게 두개야!
@Select("select * from menu")
List<Menu> findAll();
Menu findById(long id);
Menu insert(Menu menu);
Menu update(Menu menu);
void delete(long id);
}
2)
오류가 났다 왜냐하면 보따리(bean)가 두개였다 (JDBC, 마바) JDBC부분의 @repository부분을 지워주면 돼!
FrameWork의 힘!
3)
@Select("select * from menu where id=#{id}")
Menu findById(long id);
Menu insert(Menu menu);
Menu update(Menu menu);
void delete(long id);
#과 $ 차이
id 가 문자열이면 꽂아넣을 때 $는 " " 포함되어야 해
정수는 $,#이나 같아!
<interface에 쿼리사용시 문제점 2가지>
1 쿼리는 내려쓰기 되어야하는데, interface에서 보기가 안좋아!
무엇을 약속(설계도)했는지 쿼리에 파묻혀버려 (가독성 하)
2 인터페이스인데, 플랫폼에 독립적인 느낌이 필요해, 그런데 너무 mybatis에 잠식된 느낌이야
mybatis를 걷어낼때 걷어낼 것이 너무 많아!
4)
package kr.co.rland.web.repository;
import java.util.List;
//ibatis가 원래 이름이야!
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import kr.co.rland.web.entity.Menu;
//이것을 구현한 구현체를 알아서 repo에 보내주는거야!
@Mapper
public interface MenuRepository {
//jdbc 와 mybatis로 구현한게 두개야!
// @Select("select * from menu")
List<Menu> findAll();
// @Select("select * from menu where id=#{id}")
Menu findById(long id);
Menu insert(Menu menu);
Menu update(Menu menu);
void delete(long id);
}
interface
다만 최소한의 코드는 @Mapper 를 살리고, @select 와 주석조차도!!! 지워
코드 내려쓰기 등을 하는 XML을 가능한 쿼리를 쓰기가 가능해 -> 동적인 SQL도 가능해서 더 바람직해!
(4) XML 방식
resources 에 다가 넣는게 가장 낫다.
1)
마이바티스에게 이해할수 있는 구문(tag)구조와 XML위치를 알려야 해
어떻게 알아? 레퍼런스를 보자! ( https://mybatis.org/mybatis-3/getting-started.html )
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
Mapper.xml 에다가 구문을 넣어주면 돼!
2)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.rland.web.repository.MenuRepository">
<!-- 아까는 한줄에 구현해야했는데, 이제 내려쓰기도 해도 되고부담이 없어! 주석도 돼! -->
<select id="findAll" resultType="Blog">
select *
from menu
</select>
<select id="findById" resultType="Blog">
select *
from menu
where id = #{id}
</select>
이렇게 하면 기존에 Annotation 방식은 한줄로 구현해야하지만, 내려쓰기도 가능하고, 주석도 달수있게 되는 이점이 있다. (가독성 up)
3)
그러고 mybatis에게 내가 여기 있다고 알려주어야 해!
boot 라서 편한게 application-properties 에다가 해주면 됨!
application.yml이 선호 돼 왜냐하면 은 앞 서 있는 내용 따라갈 필요없이 (그런데 application-properties 에다가 하자!)
mybatis:
mapper-locations:
classpath*:mapper/*Mapper.xml
yml은 빈공백조차도 약속이라서 스페이스 하나도 조심해야해!
4)
결국 이렇게 하면 아래의 소스코는 없어도 무방하다
왜냐하면 MenuRepository 인터페이스의 구현체가 두개로 중복되기 때문이야!
package kr.co.rland.web.repository.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import kr.co.rland.web.entity.Menu;
import kr.co.rland.web.repository.MenuRepository;
//@Repository
public class jdbcMenuRepository implements MenuRepository{
@Autowired
private DataSource dataSource;
@Override
public List<Menu> findAll() {
//가져온다 : 라이브러리가 해결할 수 있는것이 아니기 때문!
String sql = "select id, name, price, regDate, categoryId from menu";
// DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
// dataSourceBuilder.driverClassName("org.mariadb.jdbc.Driver"); //사용자 계정
// dataSourceBuilder.url("jdbc:mariadb://db.newlecture.com:3306/rlanddb");
// dataSourceBuilder.username("rland"); //이부분 바꿔주면 됨!
// dataSourceBuilder.password("20220823");
//
// DataSource dataSource = dataSourceBuilder.build();
JdbcTemplate template = new JdbcTemplate(dataSource);
List<Menu> list = template.query(sql, new BeanPropertyRowMapper(Menu.class));
return list;
}
@Override
public Menu findById(long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public Menu insert(Menu menu) {
// TODO Auto-generated method stub
return null;
}
@Override
public Menu update(Menu menu) {
// TODO Auto-generated method stub
return null;
}
@Override
public void delete(long id) {
// TODO Auto-generated method stub
}
// 반복하자나!!!
//
// @Override
// public List<Menu> findAll() {
//
//
// String sql = String.format("select id, name, price, regDate, categoryId, regMemberId from menu");
// List<Menu> list = new ArrayList<>();
//
// try {
// Class.forName("org.mariadb.jdbc.Driver");
// String url = "jdbc:mariadb://db.newlecture.com:3306/rlanddb";
// Connection con = DriverManager.getConnection(url, "rland", "20220823");
//
// Statement st = con.createStatement();
// ResultSet rs = st.executeQuery(sql);
//
// // 필터링, 집계, 정렬
// while (rs.next()) // 서버의 커서를 한칸 내리고 그 위치의 레코드를 옮겨 오는 것. -> 레코드 하나가 저장되는 공간은?
// {
// long id = rs.getLong("id");
// String name = rs.getString("name");
// int price = rs.getInt("price");
// Date regDate = rs.getDate("regDate");
// int categoryId = rs.getInt("categoryId");
// long regMemberId = rs.getLong("regMemberId");
//
//
// Menu menu = new Menu(id, name, price, regDate, categoryId,1);
// list.add(menu);
// }
// con.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
// return list;
// }
}
1. 보충
(1)
2. 회고
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 64번째- 230308 [3-1-수] (0) | 2023.03.08 |
---|---|
TIL : 63번째- 230307 [3-1-화] (0) | 2023.03.07 |
TIL : 61번째- 230302 [2-4-목] (0) | 2023.03.02 |
TIL : 60번째- 230228 [2-4-화] (0) | 2023.02.28 |
TIL : 58번째- 230224 [2-3-금] (0) | 2023.02.24 |