월루를 꿈꾸는 대학생

[SpringBoot] 게시판 만들기 feat) mybatis + jQuery 본문

Programing/Spring Boot

[SpringBoot] 게시판 만들기 feat) mybatis + jQuery

하즈시 2023. 3. 8. 00:46
728x90

 

 

마리아db 관련 내용 설정 

 

application.properties

# Port
server.port=8085

# MariaDB
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3307/boot_study
spring.datasource.username=boot
spring.datasource.password=boot

# Thymeleaf
spring.thymeleaf.cache=false
#spring.thymeleaf.prefix=classpath:/templates
spring.thymeleaf.prefix=file:src/main/resources/templates
spring.thymeleaf.suffix=.html

# Dev
spring.devtools.livereload.enabled=true

#mybatis mapper xml
mybatis.mapper-locations=classpath:sqlmapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

 

html 및 코드 참고 

https://principled-ptarmigan-d63.notion.site/Springboot-Web-e204cd771c41466a8af50b26f699e869

 

Springboot Web 프로그래밍(기본소스 공유)

시나리오 - 커피메뉴를 보여주는 간단한 조회화면을 작성한다. - 단일 로우에 대한 수정작업을 하도록 한다. - 멀티 로우에 대한 수정작업을 하도록 한다. - jQuery , Json, Ajax 를 사용한다. - Controller

principled-ptarmigan-d63.notion.site

 

 

static 

- 해당 폴더에 있는 html파일의 경우 url 경로 쳐서 확인 가능 ! 

 

template

- 컨트롤러가 불러야만 확인 가능 url불가 


mvc

- 컨트롤러 

- dao : 데이터베이스 연결 

- service  : 서비스 로직 

 

-static : css , 경로

-templates : 컨트롤러에서 찾는 루트위치 

 

 

html 공통부분을 묶어서 comm에 넣어야함 

 

header

<div class="topnav">
  <a href="/">Home</a>
  <a href="/v1/coffee">커피메뉴 V1</a>
  <a href="#">커피메뉴 V2</a>
</div>

 

footer

<div class="footer">
  <h3>[Footer] Web Programming | from 프론트엔드 by IT늦공 <span style="font-size:30px;">&#9749;</span></h3>
</div>

 

요렇게 공통을 따로 뺴고 home에다가 연결하기 

home.html

<!DOCTYPE html>
<!--thymeleaf 지정-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" type="text/css" href="/css/comm.css">

</head>
<body>
<!--
<div class="topnav">
    <a href="#">Home</a>
    <a href="#">커피메뉴 V1</a>
    <a href="#">커피메뉴 V2</a>
</div>-->
<!--헤더 위치 -->
<th:block th:include="~{/comm/header}"></th:block>

<div id="main" style="font-size:large; alignment: center; padding: 10px 50px ">
    <p>Web Programming | from 프론트엔드<br>
        이 영상은 내 스스로가 공부한 내용을 기록하기 위해 작성하고 있습니다.<br>
        아주 초보적인 내용이지만 저와 같은 분들에게 도움이 되면 그 또한 좋겠습니다.
    </p>
    <p>
    <ul style="list-style-type:square;">
        <li>개발툴 : 인텔리J</li>
        <li>Java 버전 : 1.8</li>
        <li>DBMS : MaridDB</li>
        <li>View  : 타임리프</li>
        <li>Mapper : 마이바티스</li>
    </ul>
    </p>

</div>


<!--<div class="footer">
    <h3>[Footer] Web Programming | from 프론트엔드 by IT늦공 <span style="font-size:30px;">&#9749;</span></h3>
</div>-->
<!--푸터 위치 -->
<th:block th:include="~{/comm/footer}"></th:block>

</body>
</html>
</html>

db연결

dao -데이터베이스 연결하는 쿼리 있음 

service - 컨트롤러와 dao 사이에서 로직 처리를 함 

 

 

 

https://mybatis.org/mybatis-3/getting-started.html

 

mybatis – MyBatis 3 | Getting started

It's very important to understand the various scopes and lifecycles classes we've discussed so far. Using them incorrectly can cause severe concurrency problems. Dependency Injection frameworks can create thread safe, transactional SqlSessions and mappers

mybatis.org

 

<?xml version="1.0" encoding="UTF-8" ?>
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>

 

작업 방법 

 

1. 컨트롤러에서 화면에 넘길 데이터를 정의 

- autowired로 서비스를 가지고옴 

- 서비스는 컨트롤러에서 하지 않는 데이터 관련 로직을 수행 

- 서비스에 있는 doCoffeeList() 메서드로 조회 값을 넘겨서 모델에 넘긴다고 정의

- 이 시점에서는 서비스에 해당 로직 없으니까 서비스에 가서 메서드 정의가 필요 

@Controller
// 경로 시작점 지정
@RequestMapping("v1")
public class CoffeeV1 {

    // autowired로 서비스 객체 가지고 오기
    @Autowired
    CoffeeV1Service coffeeV1Service;


    @GetMapping("/coffee")
    public String doCoffee(Model model){

        /*전체 리스트 조회*/
        //디비에 있는 값들 한 행을 map 그 묶음을 list로
        List<Map<String,String>> list = coffeeV1Service.doCoffeeList();

        //System.out.println(list);
        //모델에다가 값 넣어주기 이제 웹으로 넘겨줌
        model.addAttribute("list",list);
        return "/v1/coffee";
    }

}

 

2. 서비스에서 dao 값 받아올 메서드 정의 

- autowired에서 dao 가져오기 

- 컨트롤러에서 정의한 메서드를 구현 

- 해당 메서드는 dao에 있는 doCoffeList에서 리스트르 받아서 리턴

- 해당 리턴 값을 컨트롤러에 넘겨줌 

- 다음과 같은 데이터 관련 로직을 수행 

@Service
public class CoffeeV1Service {

    @Autowired
    CoffeeV1Dao coffeeV1Dao;

    // 전체 리스트 조회
    public List<Map<String, String>> doCoffeeList() {
        // dao에서 가지고 와야 쓰지! 즉 맵퍼
        List<Map<String,String>> list = coffeeV1Dao.doCoffeeList();

        return list;
    }
}

 

3. dao로 xml과 사이 테이블 값 조회 

- mapper 어노테이션 사용 - xml과 야리토리 

- 인터페이스로 정의 및 구현은 안함 

- 그냥 리턴값이랑 메서드 이름만 정의하고 이거 내용은 짜피 sql문이라서 연결된 xml에서 구현해서 받아옴 

- 리턴이 정해져 있으니까 이거 서비스에서는 값 받은거 그대로 넘겨줌 

- xml : 실제 sql문 사용해서 값을 가지고 온 걸 dao에 넘겨줌 

// 마이바티스 쓰기위해선 mapper 어노테이션이 필요!
@Mapper
public interface CoffeeV1Dao {
    // 전체 리스트 조회
    // 인터페이스네 dao에서 매퍼를 쓰는 경우 인터페이스라고 하네
    // 리스트로 반환하는 doCoffeeList가 있다 .. doCoffeeList이 부분을 매퍼로 구현해야함!
    List<Map<String, String>> doCoffeeList();


}

 

4. xml 정의 

- namespace로 dao 경로

- id로 메서드 이름 , resultType으로 map 

- 실제 sql문 사용해서 값을 가지고 옴 

<?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">
<!--네임스페이스에서 dao 파일 경로 넣어주기 -->
<mapper namespace="com.example.coffee.dao.CoffeeV1Dao">
    <!--쿼리문 작성 보아하니 dao인터페이스에 있는 걸 여기에서 받아서 쓰나보군 return값을-->
    <!--전체리스트 조회-->

    <!--id는 dao에 있는 메서드이름-->
    <!--result type = 리턴타입인데 맵이라고 하네 -->
    <!--sql 문을 넣어서 해당 결과를 받음-->
    <select id="doCoffeeList" resultType="map">
        SELECT coffee_id, name, kind, price, DATE_FORMAT(reg_day,'%Y.%m.%d') AS reg_day, DATE_FORMAT(mod_day,'%Y.%m.%d') AS mod_day FROM coffee

    </select>
</mapper>

 

5. 컨트롤러가 위에서 받은 것들 그대로 html넘겨준 거 처리하기 

- 리스트에 있는 원소(맵)을 하나씩 가지고와서 정리 

- get 메서드로 값 추출 

<tbody id="t_body">
<!--모델에서 받은 데이터 출력-->
  <th:block th:each="coffeeV1 : ${list}">
    <tr class="tr_td">
      <td><input type="checkbox" name="coffee_id" value="ID"></td>
      <td th:text="${coffeeV1.get('coffee_id')}">ID</td>
      <td th:text="${coffeeV1.get('name')}">메뉴명</td>
      <td th:text="${coffeeV1.get('kind')}">종류</td>
      <td th:text="${coffeeV1.get('price')}">가격</td>
      <td th:text="${coffeeV1.get('reg_day')}">등록일</td>
      <td th:text="${coffeeV1.get('mod_day')}">수정일</td>
      <td><a th:href="@{/v1/update(coffee_id=${coffeeV1.get('coffee_id')})}">수정</a></td>
      <td><a th:href="@{/v1/delete(coffee_id=${coffeeV1.get('coffee_id')})}">삭제</a></td>
    </tr>
  </th:block>

 

select coffee_id, name, kind, price, date_format(reg_day,'%Y.%.%d') AS reg_day, date_format(mod_day,'%Y.%.%d') AS mod_day from coffee;

 


스프링부트에서 디비 연결 과정 

- java jdbc에서 디비릉 붙여줌 

 

 


검색 관련 sql 만들기! 

 

먼저 검색용 form을 확인 

- post 방식으로 /v1/coffee로 보냄 즉 자기 자신임 또 url이 coffee controller에 가게 됨

- submit 실행 시키면 각종 name 들 있는 태그들도 request로 보내게됨 

 

<form name="coffeeV1" autocomplete="on" action="/v1/coffee" method="post">
  <fieldset>
    <legend> [검색조건] </legend>
    <label>등록기간</label><input type="date" id="start_date" name="start_date" min="2020-01-01" max="2023-12-31">
    - <input type="date" id="end_date" name="end_date" min="2020-01-01" max="2023-12-31">
    &nbsp;&nbsp;
    <label>메뉴명</label> <input type="text" name="name">
    &nbsp;&nbsp;
    <label>종류</label> <select name="kind">
    <option value="ALL">전체</option>
    <option value="1.커피">1.커피</option>
    <option value="2.에이드">2.에이드</option>
    <option value="3.스무디">3.스무디</option>
  </select>
    &nbsp;&nbsp;<input type="submit" value="조회" style="width: 80px;height: 30px;font-weight: bold; font-size: medium">
    &nbsp;&nbsp;<button onclick="document.location='/v1/insert'" value="등록" style="width: 80px;height: 30px;font-weight: bold; font-size: medium">등록</button>
    &nbsp;&nbsp;<button onclick="document.location='/v1/'" value="삭제" style="width: 80px;height: 30px;font-weight: bold; font-size: medium">삭제</button>
  </fieldset>
</form>

 

커피 컨트롤러 

- post방식으로 매핑 

- HttpServletRequest를 파라미터로 받아서 html에 있던 것들 파라미터로 활용 

- 각종 name태그에 있던 value 받아서 사용 

- 똑같이 서비스에 doCoffee 메서드 부르는데 리퀘스트에서 받았던 파라미터들을 넣어서 활용 -> 오버로딩 

@PostMapping("/coffee")
public String doCoffeePost(HttpServletRequest request, Model model){
    // html form으로 받은 리퀘스트 항목의 값을 추출

    String strStart_date = request.getParameter("start_date");
    String strEnd_date = request.getParameter("end_date");
    String strName = request.getParameter("name");
    log.info(strName);
    String strKind = request.getParameter("kind");
    // 이걸로 터미널창에 로그 확인 가능
    log.info(strKind);


    // 전체 리스트 조회 오보로딩
    List<Map<String,String>> list = coffeeV1Service.doCoffeeList(strStart_date,strEnd_date,strName,strKind);
    model.addAttribute("list",list);

    return "/v1/coffee";
}

 

service 

- 나머지 다 같고 dao 로 이동 

// 파라미터만 다른 오버로딩
public List<Map<String, String>> doCoffeeList(String strStartDate, String strEndDate, String strName, String strKind) {
    // dao에서 가지고 와야 쓰지! 즉 맵퍼
    List<Map<String,String>> list = coffeeV1Dao.doCoffeeList(strStartDate,strEndDate,strName,strKind);

    return list;
}

 

 

dao 

- 결국 같음 파라미터만 다르다 

- 즉 이걸 보면 xml에 있는 sql에다가 해당 파라미터로 조회 하면 됨! 

// 전체리스트 조회 - 함수 오버로딩
List<Map<String, String>> doCoffeeList(String strStart_date,String strEnd_date,String strName,String strKind);

 

xml

- where로 조건을 넣음 여기서는 choose = if , else if = otherwise 를 사용 

- 파라미터로 받은 것들 활용해서 조건을 분기시키고 #{파라미터} 로 직접적으로 sql에 사용

<?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">
<!--네임스페이스에서 dao 파일 경로 넣어주기 -->
<mapper namespace="com.example.coffee.dao.CoffeeV1Dao">
    <!--쿼리문 작성 보아하니 dao인터페이스에 있는 걸 여기에서 받아서 쓰나보군 return값을-->
    <!--전체리스트 조회-->

    <!--id는 dao에 있는 메서드이름-->
    <!--result type = 리턴타입인데 맵이라고 하네 -->
    <!--sql 문을 넣어서 해당 결과를 받음-->
    <select id="doCoffeeList" resultType="map">
        SELECT coffee_id, name, kind, price, DATE_FORMAT(reg_day,'%Y.%m.%d') AS reg_day, DATE_FORMAT(mod_day,'%Y.%m.%d') AS mod_day
        FROM coffee
        WHERE 1=1
        <!--등록 기간 쿼리 -->
        <!--if = choose  여기서 인터페이스에 있는 파라미터를 여기서 쓰네! -->
        <choose>
            <when test="strStart_date == null">
                AND reg_day >= date_add(now(), INTERVAL-7 DAY)
            </when>
            <otherwise>
                AND reg_day >= DATE_FORMAT( #{strStart_date}, '%Y,%m,%d')
                AND reg_day <![CDATA[ < ]]> date_add(DATE_FORMAT(#{strEnd_date},'%Y,%m,%d'), INTERVAL+1 DAY)
            </otherwise>
        </choose>

        <if test="strName != null and strName !=''">
            AND name like CONCAT(#{strName},'%')
        </if>

        <!--종류 쿼리-->
        <if test="strKind != null and strKind != 'ALL'">
            AND kind = #{strKind}
        </if>

    </select>

</mapper>

 

다시 컨트롤러에서 받아서 html에 보내면 끝! 

 


나머지도 거의 동일함 

코드 확인 하기 

https://github.com/suhyun96/SpringBoot/tree/main/coffee

 

GitHub - suhyun96/SpringBoot: 스프링 부트 공부한 내용 정리용

스프링 부트 공부한 내용 정리용. Contribute to suhyun96/SpringBoot development by creating an account on GitHub.

github.com


참고 유튜브 영상

https://youtu.be/AxskTLjFyoA

 

 

728x90