보라코딩
스프링부트 spring mvc 기본 구조 (MyBatis, Oracle DB 연동) 본문
java
com/tastemate/controller/StroreController
store부분을 맡아서 StoreController.java를 생성했다.
controller에서는 service를 @autowired
import com.tastemate.domain.StoreVO;
import com.tastemate.service.StoreService;
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 java.util.List;
@Controller
@RequestMapping("/store/*")
public class StoreController {
@Autowired
private StoreService service;
public String get(Model model){
List<StoreVO> storeVO = service.store_get();
model.addAttribute("storeList", storeVO);
return "/store/list";
}
}
com/tastemate/domain/StoreVO
DB 확인만 하기 위해 간단하게 만들었다.
@Data 어노테이션 사용시 toString, 생성자, getter setter 모두 해결됨
import lombok.Data;
@Data
public class StoreVO {
private int storeIdx;
private String name;
}
com/tastemate/mapper/StoreService
서비스에서는 mapper을 @autowired 하였다.
import com.tastemate.domain.StoreVO;
import com.tastemate.mapper.StoreMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StoreService {
@Autowired
private StoreMapper mapper;
public List<StoreVO> store_get() {
List<StoreVO> storeList = mapper.store_getList();
return storeList;
}
}
com/tastemate/mapper/StoreMapper (인터페이스!!!)
import com.tastemate.domain.StoreVO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Mapper
public interface StoreMapper {
public List<StoreVO> store_getList();
}
application.properties
url과 username, password는 알맞게 바꿔주기
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=mystudy
spring.datasource.password=mystudypw
# XML location
mybatis.mapper-locations=classpath:mappers/*.xml
#MYBATIS
mybatis.type-aliases-package=com.tastemate.domain
mybatis.configuration.map-underscore-to-camel-case=true
스프링부트의 Thymeleaf 템플릿 결과는 캐싱하는 것이 디폴트 값이다.
즉, 개발할 때 Thymeleaf를 수정하고 브라우저를 새로고침하면 바로 반영이 되지 않는다.
따라서 개발을 할 때에는 false로 해 주는 것이 재시작 없이 새로고침만으로 반영되게 하는 것이 편하다.
spring.thymeleaf.cache=false
resources 내 mapper.xml
resources/com/tastemate/mapper/StoreMapper.xml
mapper.xml 생성필요
이때 이름은 위에 인터페이스로 만든 mapper와 이름 동일하게 해준다.
우선 select로 list 가져오는 것만!
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tastemate.mapper.StoreMapper">
<select id="store_getList" resultType="com.tastemate.domain.StoreVO">
select * from store
</select>
</mapper>
id를 mapper 인터페이스와 동일하게 해야함!!!
view 화면
resources/templates/store/list.html
templates 에 view 파일을 생성해준다.
내 경우는 store 밑에 list.html을 만들어주었다.
그래서 앞에 controller에서 아래와 같은 어노테이션을 사용했었다.
@RequestMapping("/store/*")
@GetMapping("/list")
list.html 파일의 경우
맨위에 이렇게 써주면 타임리프로 사용가능!
<html lagn="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
타임리프로 잘 가져올 수 있는지만 확인해보았다.
<html lagn="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<th:block th:replace="header_footer/header :: headerFragment"></th:block>
<head>
<meta charset="UTF-8">
<title>store list</title>
</head>
<body>
<div>
<h5 th:text="${storeList}"></h5>
</div>
<div th:each="storeVO : ${storeList}">
<span th:text="${storeVO.storeIdx} + ' & ' + ${storeVO.name}"></span>
</div>
<th:block th:replace="header_footer/footer :: footerFragment"></th:block>
</body>
</html>
header.html
<!--headerFragment 선언-->
<div th:fragment="headerFragment">
<!doctype html>
<html lang="ko">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<style>
.navbar {
background-color: #fff;
box-shadow: 0 0.5px 0 0 #dee2e6;
}
.navbar-brand,
.nav-link {
color: #343a40;
}
.navbar .navbar-brand {
font-weight: 600;
}
.navbar .navbar-nav .nav-link {
font-weight: 500;
}
.navbar .btn-outline-dark {
margin-left: auto;
}
</style>
<title>TasteMate</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<a class="navbar-brand" href="#">TasteMate</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">커뮤니티</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">맛집</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">내강의장</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">꿀팁</a>
</li>
</ul>
<form class="form-inline mx-auto">
<input class="form-control mr-sm-2" type="search" placeholder="검색" aria-label="Search">
<button class="btn btn-outline-dark my-2 my-sm-0" type="submit">검색</button>
</form>
<div class="ml-auto">
<button class="btn btn-outline-dark ml-2" type="button">회원가입</button>
<button class="btn btn-outline-dark ml-2" type="button">로그인</button>
</div>
</div>
</nav>
footer.html
<!--footerFragment 선언-->
<div th:fragment="footerFragment">
<!-- Footer -->
<footer class="page-footer font-small blue pt-4" style="background-color: #f8f9fa; border-top: 0.5px solid #dee2e6;">
<!-- Footer Links -->
<div class="container text-center text-md-left mt-5">
<!-- Grid row -->
<div class="row mt-3">
<!-- Grid column -->
<div class="col-md-3 col-lg-4 col-xl-3 mx-auto mb-4">
<!-- Content -->
<h6 class="text-uppercase font-weight-bold">TasteMate</h6>
<hr class="deep-purple accent-2 mb-4 mt-0 d-inline-block mx-auto" style="width: 60px;">
<p>Find friends, enjoy food. This is the TasteMate community. Let's enjoy it together.</p>
</div>
<!-- Grid column -->
<!-- Grid column -->
<div class="col-md-2 col-lg-2 col-xl-2 mx-auto mb-4">
<!-- Links -->
<h6 class="text-uppercase font-weight-bold">Products</h6>
<p>
<a href="#!">커뮤니티</a>
</p>
<p>
<a href="#!">맛집</a>
</p>
<p>
<a href="#!">내강의장</a>
</p>
<p>
<a href="#!">꿀팁</a>
</p>
</div>
<!-- Grid column -->
<!-- Grid column -->
<div class="col-md-3 col-lg-2 col-xl-2 mx-auto mb-4">
<!-- Links -->
<h6 class="text-uppercase font-weight-bold">Useful links</h6>
<p>
<a href="#!">Your Account</a>
</p>
<p>
<a href="#!">Become an Affiliate</a>
</p>
<p>
<a href="#!">Shipping Rates</a>
</p>
<p>
<a href="#!">Help</a>
</p>
</div>
<!-- Grid column -->
<!-- Grid column -->
<div class="col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4">
<!-- Links -->
<h6 class="text-uppercase font-weight-bold">Contact</h6>
<p>
<i class="fas fa-home mr-3"></i> New York, NY 10012, US</p>
<p>
<i class="fas fa-envelope mr-3"></i> info@example.com</p>
<p>
<i class="fas fa-phone mr-3"></i> + 01 234 567 88</p>
<p>
<i class="fas fa-print mr-3"></i> + 01 234 567 89</p>
</div>
<!-- Grid column -->
</div>
<!-- Grid row -->
</div>
<!-- Footer Links -->
<hr>
<!-- Call to action -->
<ul class="list-unstyled list-inline text-center py-2">
<li class="list-inline-item">
<h5 class="mb-1">Register for free</h5>
</li>
<li class="list-inline-item">
<a href="#!" class="btn btn-outline-dark">Sign up!</a>
</li>
</ul>
<!-- Call to action -->
<hr>
<!-- Social buttons -->
<ul class="list-unstyled list-inline text-center">
<li class="list-inline-item">
<a class="btn-floating btn-fb mx-1" href="#!">
<i class="fab fa-facebook-f"> </i>
</a>
</li>
<li class="list-inline-item">
<a class="btn-floating btn-tw mx-1" href="#!">
<i class="fab fa-twitter"> </i>
</a>
</li>
<li class="list-inline-item">
<a class="btn-floating btn-gplus mx-1" href="#!">
<i class="fab fa-google-plus-g"> </i>
</a>
</li>
<li class="list-inline-item">
<a class="btn-floating btn-li mx-1" href="#!">
<i class="fab fa-linkedin-in"> </i>
</a>
</li>
<li class="list-inline-item">
<a class="btn-floating btn-dribbble mx-1" href="#!">
<i class="fab fa-dribbble"> </i>
</a>
</li>
</ul>
<!-- Social buttons -->
<hr>
<!-- Copyright -->
<div class="text-center py-3">
© 2023 TasteMate Inc.
</div>
<!-- Copyright -->
</footer>
<!-- Footer -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
다음 참고하면 좋은 글 :)
스프링부트 게시판 CRU (타임리프 사용)
READ BoardController @Autowired private BoardService service; @GetMapping("/list") public String getList(Model model){ List boardList = service.board_getList(); model.addAttribute("boardList", boardList); return "/board/list"; } @GetMapping({"/get", "/upda
boracoding.tistory.com
'코딩 > Spring' 카테고리의 다른 글
Day101_230522_3차 프로젝트 구현중 (맛집) (0) | 2023.05.22 |
---|---|
스프링부트 게시판 CRUD (타임리프 사용) (0) | 2023.05.20 |
Day100_230519_3차 프로젝트 설계 (0) | 2023.05.19 |
스프링 로그 자동으로 찍는 기능 (0) | 2023.05.19 |
Day99 _ 3차 프로젝트 시작 (2023.05.18 ~ 2023.06.21) (0) | 2023.05.18 |