2023. 6. 12. 19:19ㆍSpring Boot
Spring Boot
Index.jsp
IndexController.java
Mybatis.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:include page="/WEB-INF/views/template/Top.jsp" />
<div class="container" style="margin-top: 50px">
<div class="jumbotron bg-info">
<h1>
Spring Framework <small>MyBatis Framework</small>
</h1>
</div>
<!--jumbotron-->
<fieldset class="form-group border p-3">
<legend class="w-auto px-3">마이바티스 프레임워크</legend>
<h1 class="display-4">마이 바티스 사용 방법</h1>
<span class="text-danger font-weight-bolder">${time}</span>
<ul class="list-unstyled">
<li><a href="<c:url value="/Mybatis/annotation"/>">어노테이션방식</a></li>
<li><a href="<c:url value="/Mybatis/xml"/>">XML방식</a></li>
</ul>
<h1 class="display-4">동적 SQL(XML방식)</h1>
<span class="text-danger font-weight-bolder">${message}</span>
<h3>if 태그</h3>
<ul class="list-unstyled">
<li><a href="<c:url value="/Mybatis/If1.do?title=자바"/>">WHERE절
일부에 사용 첫번째</a></li>
<li><a
href="<c:url value="/Mybatis/If2.do?title=자바&name=김길동&content=안드로이드"/>">WHERE절
일부에 사용 두번째</a></li>
</ul>
<h3>choose~when~otherwise 태그</h3>
<a
href="<c:url value="/Mybatis/choose.do?title=자바&name=김길동&content=안드로이드"/>">WHERE절
일부에 사용</a>
<h3>where 태그</h3>
<a
href="<c:url value="/Mybatis/where.do?title=자바&name=김길동&content=안드로이드"/>">where태그로
where절 구성</a>
<h3>trim 태그</h3>
<ul class="list-unstyled">
<li><a
href="<c:url value="/Mybatis/trim1.do?title=자바&name=김길동&content=안드로이드"/>">검색문</a></li>
<li><a
href="<c:url value="/Mybatis/trim2.do?no=21&title=자바&content=안드로이드"/>">수정문</a></li>
</ul>
<!-- update 하고자 하는 칼럼을 동적으로 포함시키기 위해 사용 -->
<h3>set 태그</h3>
<a href="<c:url value="/Mybatis/set.do?no=21&title=안녕&content=인사"/>">수정문</a>
<h3>foreach 태그</h3>
<a href="<c:url value="/Mybatis/foreach.do"/>">foreach태그</a>
<h3>이메일 삭제</h3>
<form method="post" action="<c:url value="/Mybatis/foreachExam.do"/>">
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="1" name="email">메일 1
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="2" name="email">메일 2
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="3" name="email">메일 3
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="14" name="email">메일 14
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="15" name="email">메일 15
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="16" name="email">메일 16
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="17" name="email">메일 17
</label>
</div>
<div class="form-check">
<label class="form-check-label"> <input type="checkbox"
class="form-check-input" value="18" name="email">메일 18
</label>
</div>
<input type="submit" value="삭제" class="btn btn-danger" />
</form>
</fieldset>
</div>
<!--container-->
<jsp:include page="/WEB-INF/views/template/Footer.jsp" />
결과) 2개
풀이
MybatisController.java
package com.kosmo.springapp.basic.mybatis;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/*
1. 컨트롤러 작성
1-1.서비스 주입
1-2.서비스의 메소드 호출
2. 서비스 작성(@Service 어노테이션 부착:클래스)
2-1.생성자 인젝션으로 매퍼 인터페이스를 주입 받는다
2-2.매퍼 인터페이스의 메소드 호출
3. 매퍼 인터페이스 작성(@Mapper 어노체이션 부착:인터페이스)
어노테이션방식과 XML방식이 있다
XML방식으로 서비스시에는 반드시 마이바티스 구성을 위한 빈(MyBatisConfig.java)을 만들자
단,어노테이션 방식일때는 필수사항이 아니다
※쿼리문이 복잡할때 혹은 동적 쿼리 적용시에는 XML방식이 유리하다.
※바인딩(쿼리 결과와 자바빈의 매핑) 흐름 절차
MyBatisConfig.java에 등록한 빈이 사전에 컨테이너에 등록 되어 있어야 한다
서비스의 메소드 호출->서비스에서 매퍼 인터페이스의 메소드 호출(XML기반)->
매퍼파일(mybatis.xml)에서 매퍼 인터페이스의 메소드명과 동일한 id값을 찾는다->
해당 아이디값의 쿼리문이 실행된다
마이바티스 구성빈(MyBatisConfig) 미 코드시 어노테이션 방식은
매퍼 인터페이스의 메소드 호출시 바인딩되서(자바객체와 쿼리문) 정상적으로 실행된다
단,XML방식은 매퍼 인터페이스의 메소드 호출시 메소드와 쿼리문이 바인딩 안되서
Invalid bound statement (not found): com.kosmo.springapp.basic.mybatis.MyBatisMapper.getTimeByXml
org.apache.ibatis.binding.BindingException에러 발생
해결책-자바코드로 마이바티스 구성 빈을 작성한다
*/
@Controller
@RequestMapping("/Mybatis")
public class MyBatisController {
//서비스 호출-서비스 주입 받기
@Autowired
private MyBatisService service;
@GetMapping("/annotation")
public String annotation(Model model) {
model.addAttribute("time","ANNOTATION방식:"+service.getTimeByAnnotation());
//뷰정보 반환
return "mybatis08/Mybatis";
}///////////////
@GetMapping("/xml")
public String xml(Model model) {
model.addAttribute("time","XML방식:"+service.getTimeByXml());
//뷰정보 반환
return "mybatis08/Mybatis";
}///////////////
@GetMapping("/If1.do")
public String if1(@RequestParam Map map,Model model) {
//서비스 호출
List<Map> articles=service.if1(map);
for(Map article:articles) {
System.out.println(article.get("NO"));
}
//데이타 저장
model.addAttribute("message", "갬색된 총 글 수:"+articles.size());
//뷰정보 반환
return "mybatis08/Mybatis";
}///////////////////////
}
요청 받음 /Mybatis/annotation, /Mybatis/xml
time의 키로 service.getTimeByAnnotation()을 값으로
서비스 호출 -서비스 주입받음
MyBatisservice.java
package com.kosmo.springapp.basic.mybatis;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//※서비스의 메소드명은 업무처리 로직에 해당하는 관련있는 이름으로 주로 정의하자
@Service
public class MyBatisService {
//생성자 인젝션으로 MyBatisMapper(DAO역할)를 주입 받자
private MyBatisMapper mapper;
@Autowired//생략 가능
public MyBatisService(MyBatisMapper mapper) {
this.mapper = mapper;
}
public String getTimeByAnnotation() {
/*
매퍼 인터페이스의 getTimeByAnnotation()호출시 어노테이션에 작성한 쿼리가 실행된다
실행된 쿼리 결과를 메소드의 반환타입으로 매핑시킨다
*/
return mapper.getTimeByAnnotation();
}//////////////
public String getTimeByXml() {
/*
매퍼 인터페이스의 getTimeByXml()호출시 매퍼파일(mybatis.xml)에
메소드명과 동일한 id속성을 가진 쿼리가 실행된다.
실행된 쿼리 결과를 메소드의 반환타입으로 매핑시킨다
즉 매퍼파일의 resultType속성은 메소드의 반환타입과 일치 시키자
*/
return mapper.getTimeByXml();
}//////////////////////
public List<Map> if1(Map map) {
return mapper.findWithTitleLike(map);
}
}
service를 호출 받으면
를 호출하면 MybatisMapper의 mapper를 호출
MyBatisMapper.java
String getTimeByAnnotation();은 public abstract를 생략한 추상 메소드
결과)
xml방식)
MyBatisController.java
MyBatisService.java
getTimeByXml()호출
를 호출하면 MybatisMapper의 mapper를 호출
인터페이스 MyBatisMapper.java
여기서 sql문이 작성되지 않았다. 그럼 xml을 찾기 위해 @Mapper를 지정하고, 그 경로를 지정하기 위해
MyBatisConfig.java를 생성했다
MyBatisConfig.java
package com.kosmo.springapp.basic.mybatis;
import javax.sql.DataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.kosmo.springapp.basic.database.DatabaseConfig;
//※어노테이션이 아닌 XML방식으로 쿼리 실행시
@Configuration
//@Mapper가 붙은 매퍼 인터페이스를 스캔
//value={매퍼인터페이스들의 패키지 나열}
//sqlSessionFactoryRef는 SqlSessionFactory빈의 아이디 설정
@MapperScan(value = {"com.kosmo.springapp.basic.mybatis"},sqlSessionFactoryRef = "sqlSessionFactory")
public class MyBatisConfig {
//https://mybatis.org/spring/ko/factorybean.html
//생성자 인젝션을 통해 ApplicationContext를 컨테이너로 부터 받는다
private final ApplicationContext applicationContext;
public MyBatisConfig(ApplicationContext applicationContext) {
System.out.println("스프링 컨테이너 부터 받은 ApplicationContext:"+applicationContext);
this.applicationContext = applicationContext;
}
//1.DatabaseConfig를 필드 인젝션으로 주입
//@Autowired
//private DatabaseConfig databaseConfig;
//메소드명이 아이디임으로 sqlSessionFactoryRef속성의 값과 일치시키자
//DatabaseConfig.java의(@Bean의 아이디 미 지정시)
//메소드명과 sqlSessionFactory메소드의 인자명을 일치 시켜야 한다
//단,일치하지 않더라도 타입기반 주입이기때문에 주입은 된다
@Bean
//1.DatabaseConfig를 필드 인젝션으로 주입
//public SqlSessionFactory sqlSessionFactory() {
//2.메소드의 인자로 DataSource주입 받을시
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
SqlSessionFactory factory=null;
try {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//데이타 소스 설정:히카리로 설정-DatabaseConfig를 필드 인젝션으로 주입받을시
//1.DatabaseConfig를 필드 인젝션으로 주입
//factoryBean.setDataSource(databaseConfig.dataSource());
//2.메소드의 인자로 DataSource주입 받을시
factoryBean.setDataSource(dataSource);
//타입 별칭을 적용할 패키지 경로 설정
factoryBean.setTypeAliasesPackage("com.kosmo.springapp");
//매퍼파일의 경로 설정
factoryBean.setMapperLocations(applicationContext.getResources("classpath:mybatis/mapper/**/*.xml"));
//SqlSessionFactoryBean의 getObject()로 SqlSessionFactory객체 얻기
factory=factoryBean.getObject();
}
catch(Exception e) {e.printStackTrace();}
return factory;
}////////////////////////////
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
classpath로 경로 src/main/resources 이하 mybatis/mapper/mybaitis.xml을 생성
mybaitis.xml
<?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="com.kosmo.springapp.basic.mybatis.MyBatisMapper">
<!--매퍼 인터페이스의 메소드명이 아이디(id)가 된다-->
<select id="getTimeByXml" resultType="String">
SELECT SYSDATE FROM DUAL
</select>
<!-- 동적 SQL 연습 -->
<select id="findWithTitleLike" parameterType="Map" resultType="Map">
SELECT * FROM onememo
WHERE 1=1
<if test="title != null">
AND title LIKE '%' || #{title} || '%'
</if>
</select>
</mapper>
결과)
동적 sql(xml방식)
Mybatis.jsp
If1.do 요청
MyBatisController.java
service호출
MybatisService.java
xml파일 호출
결과)
'Spring Boot' 카테고리의 다른 글
74일차 2023-06-22 (0) | 2023.06.22 |
---|---|
67일차 2023-06-13 (0) | 2023.06.13 |
65일차 2023-06-09 (0) | 2023.06.09 |
64일차 2023-06-08 (0) | 2023.06.08 |
63일차 2023-06-07 (0) | 2023.06.07 |