배움 __IL/TIL 1기

TIL : 64번째- 230308 [3-1-수]

Mo_bi!e 2023. 3. 8. 18:10

I. 들어가며

update에서 파라미터 타입 쓰면 그 안에서 게터로 쓰는거야 이걸로 쿼리완성해! 

왜냐하면 update는 client에서 입력을 한 값model(Menu)에 담았는데,

이 담은 값을 getter를 이용해서 받아온 뒤 DB에 저장하기 때문이야

(어제까지 seter를 생각한 이유는 반대로 select로 생각했기 때문이야)

II. mybatis

1. foreach

(1) 필요성

아주 유용한 것으로 알 수있다

값을 그냥 뽑아내는 경우가 아니라 컬렉션으로 담아서, 그 안의 내용을 foreach순회하는 능력이있어!

왜 필요하냐면 반복적인 쿼리문을 작성할 떄 필요해

 

(2) 용도

예컨데 반복적인 쿼리문으로 id를 뽑아낼때 이용이된다.

 

 

(3) 실습

1)

<MenuRepositoryMapper.xml>

<select id="findAllByIds" resultType="kr.co.rland.web.entity.Menu"> 
    select *
    from menu
    <where>
                <!-- ids에서 꺼내서 id로 가 
                "ID in (" 으로 시작부분 
                출력되고, 콤마나오고 결국 ) 가 나와
                컬렉션은 null일수는 없어! -->
                
        <foreach item="id2"  collection="ids"
            open="id in (" separator="," close=")">
              #{id2}
        </foreach>
      </where>
</select>

여기서 where로 시작하고, 컬렉션 ids에서 뽑아서 id의 item에 담는다

담은 item은 #{id}로 담아준다

이 경우 id in ( 으로 시작해서 반복해서 콤마(,) 로 시작해서 ) 로 끝낸다.

@Mapper
public interface MenuRepository {
	//jdbc 와 mybatis로 구현한게 두개야!
	
	List<Menu> findAll();

//	@Select("select * from menu")
	List<Menu> findAll(	Integer offset, 
						Integer size, 
						String query,
						Integer categoryId,
						Integer price,
						String orderField,
						String orderDir
						);
	
	List<Menu> findAllByIds(List<Long> ids);

가장 아래 findAllByIds 를 이용한다.

@AutoConfigureTestDatabase(replace = Replace.NONE)
@MybatisTest
class MenuRepositoryTest {

	//이거를 쓰려면 스프링의 IoC 컨테이너를 load해야해!
	//컨테이너에 담긴적 없으면 본 repo는 null이야
	@Autowired
	private MenuRepository repository;
	
//	@Test
	void testFindAll() {
//		assertNull(repository);
		
		List<Menu> list= repository.findAll(0, 10, null, null, null, "regDate", "desc");
		System.out.println(list);
	}
	
	@Test
	void testFindAllByIds() {
		
		List<Long> ids = new ArrayList<>();
		ids.add(616L);
		ids.add(617L);
		ids.add(713L);
		ids.add(737L);
		
		List<Menu> list= repository.findAllByIds(ids);
		System.out.println(list);
	}

//	@Test

여기에다가 List컬렉션에 ids 참조명에다가 추가해준다. 추가한것을 lis참조명에 추가해준다

그리고 마이바티스에 전달이된다.

 

ids는 오로지 id값들을 저장하는 컬렉션이다.

id값을 받아서 where id in {id} 역할을 위한 것이다.

 

2. 패키지명 미리 지정하기

mybatis.type-aliases-package=kr.co.rland.web.entity
 <update id="update" parameterType="Menu">
  		update menu
  		<trim prefix="SET" suffixOverrides=",">
  			<if test="name != null">name=#{name},</if>
			<if test="price != null">price=#{price},</if>
			<if test="img != null">img=#{img}</if>						
		</trim>
		where id=#{id}
  </update>

여기서 parametrType을 패키지명 없이 Menu만 설정하면 바로 가능해!

 

 

3. 컬럼명 매핑

(1) 들어가며

mysql은 주로 소문자와 구분자는 언더바(_) 로 구분한다

 

mysql은 컬럼이나 파일명이 파일시스템을 그대로 따라가는거야!

왜냐 현재 mysql은 리눅스의 파일시스템이고, 리눅스는 소문자야

(ex:  reg_date -> regDate)

즉 mysql컬럼명 방식을 camelnotation방식이다.

 

(2) 컬럼이름 매핑위한 두가지 방식

마이바티스 VS 시퀄방식

 

(3) 마이바티스의 매핑정보 심기

<mapper namespace="kr.co.rland.web.repository.MenuRepository">
  
  <!-- 컬럼이름 매핑  -->
  	<resultMap id="menuResultMap" type="Menu">
		  <result property="regDate" column="reg_date"/>
	</resultMap>
  
  
  <!-- 아까는 한줄에 구현해야했는데, 이제 내려쓰기도 해도 되고부담이 없어! 주석도 돼! -->
  <!--  resultType 대신에 resultMap을 이용해-->
  
  <select id="findAll" resultMap="menuResultMap"> 
  <!-- resultType이 무엇이냐 modle을 넣어주자 -->
	   	select *
	  	from menu
	  	<trim prefix="WHERE" prefixOverrides="AND |OR ">
	  	
	  		<if test="query != null">
	  		name like '%${query}%'
	  		</if>
	  		
			<if test="price != null">	  		
	  		and price > #{price}
	  		</if>
	  		
			<if test="categoryId != null">	
	  		and categoryId=#{categoryId}
	  		</if>
	  		
 		</trim>
  		
		order by ${orderField} ${orderDir}
		limit #{size} offset #{offset}
  </select>
  
    <select id="findAllByIds" resultMap="menuResultMap"> 
  		select *
  		from menu
  		<where>
			  		<!-- ids에서 꺼내서 id로 가 
			  		"ID in (" 으로 시작부분 
			  		출력되고, 콤마나오고 결국 ) 가 나와
			  		컬렉션은 null일수는 없어! -->
		    <foreach item="id2"  collection="ids"
		        open="id in (" separator="," close=")">
		          #{id2}
		    </foreach>
		  </where>
  </select>

resultMap 으로 컬럼 이름 mapping이 가능해 리눅스처럼하기위해서

그리고 지정한 매핑을 아래 구문에다가 resultMap으로 이용이 가능하게끔 할 수 있어!

 

Menu라는 모델menuResultMap으로 우선 매핑을 해준다

한편 MySQL에 컬럼명은 reg_date인데, 이것을 Menu 모델propertyregDate 로 mapping시켜준다

 

application.properties 에서 mybatis.type-aliases-package 등에 패키지명을 사전에 mapping해준다.

그 결과 select 구문도 resultType대신에 resyltMap으로 menuResultMap으로 손쉽게 가능하다

 

 

2) 그외

bind를 이용해서 연산하게끔 할수도 있어!

multi-db 는 오라클과 db2(데이터 소스 같이쓰는겅우)를 섞어서 가능하다 

 

3) 

스프링부트 안쓰면 configuration에서 다 설정 해주어야해! 부트 덕분에 가능해

 데이터소스 관련 설정 스프링 마이바티스'에게' 직접해주어야해 (이 경우 설정도 어디에서 했는지도 설정 해줘야해!)

 

스프링부트에서 interface에다가 구현은 mapper에다가 하는거야 이정도면 왠만한거는 다 한 것이고 해결이 가능해!

interface에서 @Mapper걷어내면 연결을 못하는거야

 

mapper.xml에서 구현한것을 mapper 보따리(SQL세션팩토리)에 담는데, 만약 부트에 @mapper가 없으면 부트(IoC컨테이너)로 보따리가 못가...

이런경우 직접꺼내서 repository를  직접구현해야해!

 

그런데 @mapper지워야하는경우가 있나? 있어

인터페이스를 플랫폼, 기술독립적으로 온전하게 건드리면 안되는 상황이있으면 그럴수있고,

메소드 오버로드가 없어서 findAll() 인자 다 넣어야하는데, 이것이 복잡할때 이용이 가능해!

직접 구현하려면 보따리것을 직접 꺼내써야해

 

4)

mapper 구현체 (sql세션)를 담아두는것을 SQL세션팩토리

(스프링부트의 bean을 담아두는것(IoC컨테이너)것의 자료형은 application context)

(스프링부트에서 mybatis 관련 설정등을 저장하는 클래스는 mapperClass)

컨테이너의 mybatis에서 자료형sql세션 팩토리

 

5)

그러면 autowired없이 끊어진상태에서 가져다 쓰자!

 

sql세션팩토리 / sql세션 두가지야

다시 정리하면 SqlSessionFactorybootapplication context과 같은 자료명 이고,

sql session 은 resultSet과 같은 sql과 관련된 각각의 객체이다.

 

 

만약 오토와이어드 없애면 다음과 같은 에러메시지가 나와!

 

 

 

 

(4) 시퀄방식

 

 

 

 


1. 보충

(1) 

 

 

 

 

2. 회고 

1) mybatis에서 어떻게 보면 따라갈만 한데 생각보다 의도대로 녹록치는  않다.

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 66번째- 230310 [3-1-금]  (0) 2023.03.10
TIL : 65번째- 230309 [3-1-목]  (0) 2023.03.09
TIL : 63번째- 230307 [3-1-화]  (0) 2023.03.07
TIL : 62번째- 230304 [3-1-월]  (0) 2023.03.06
TIL : 61번째- 230302 [2-4-목]  (0) 2023.03.02