배움 __IL/TIL 1기

TIL : 62번째- 230304 [3-1-월]

Mo_bi!e 2023. 3. 6. 18:39

I. Mybatis

1. 들어가며

(1) 의의

MybatisSQL과 그것을 쿼리하는 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