Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

wintertreey 님의 블로그

@MVC DB연동3 MyBatis. @Mapper. th:obejct * th:field. 본문

카테고리 없음

@MVC DB연동3 MyBatis. @Mapper. th:obejct * th:field.

wintertreey 2024. 7. 21. 14:32

mybatis의장점 

클래스와 sql문의 분리. 유지보수가 편하다.

 

 

Datamapininter.java

데이터연동을위한 어노테이션걸어준다. 

package pack.model;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import pack.controller.FormBean;

@Mapper
public interface DataMappingInter {
	
	@Select("select * from sangdata")
	List<SangpumDto> selectAll();
	
	@Select("select code, sang, su, dan from sangdata where sang like concat('%', #{searchValue}, '%')")//mariadb sql
	// oracle : like '%'||#{searchValue}||'%'
	List<SangpumDto> selectSearch(FormBean bean);
	
}

@Mapper

의미를 보면 @Mapper는 마커 인터페이스라는 것이다.

기능이 있는게 아니라 마커, 즉 무언가 표시를 하기 위한 인터페이스를 의미한다.

즉, @Mapper는 단순히 '이것은 매퍼입니다!!'라는 것을 표시하기 위한 어노테이션이라는 것이다.

 

중요한 것은 @Mapper와 같이 쓰이는 @MapperScan이지 굳이 @Mapper를 쓰지 않고 커스텀 어노테이션을 생성해서 사용해도 된다.

 

파일의 흐름 

 

index --->  ListController ----->  list

              DataDao 

                DataMappingInter

 

 

 

@Slf4j

package pack.model;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import lombok.extern.slf4j.Slf4j;
import pack.controller.FormBean;

@Repository
@Slf4j //로그출력: 롬복이 지원해줌
public class DataDao {
	private Logger logger= LoggerFactory.getLogger(this.getClass());
	@Autowired
	private DataMappingInter inter;
	
	public List<SangpumDto> getDataAll(){
		List<SangpumDto> list = inter.selectAll();
		System.out.println("list.size:"+ list.size());
		logger.info("list.size:"+ list.size()); 
	
		return list;
	}

 

System.out.println("list.size:"+ list.size());
logger.info("list.size:"+ list.size()); 

이 둘은 같은 의미의 문장이다. 개발자가 출력해서 확인해보고자 하는 용도..

 

+ 히카리 풀링이 콘솔창에 찍힌것을 확인할 수 있다. 

 

 


작업 흐름

HTML > MemController > DataProcess > DataMapperInterface > HTML

                @Controller        @Repository       @Mapper

MemDto, MemBean : 저장소

 

시작페이지 

이번엔 시작페이지도 templates안에 위치하게 두었다. 

@Controller
public class MemController {
	@Autowired
	private DataProcess dataProcess;
	
	@GetMapping("/") 
	public String chulbal() {
		return "chulbal";
	}

 

요청명이 포트번호까지만 들어왔을때 출발페이지보여줌. 즉 시작페이지를 chulbal 로 해두는것.

<body>
메인페이지
<br>
<a href="/list">회원관리(@MVC - MyBatis : CRUD)</a>
</body>

url에 localhost를 치면 메인페이지가 뜬다. 

 

 

전체자료읽기

@GetMapping("list")
	public String list(Model model) { 
		ArrayList<MemDto> list = (ArrayList<MemDto>)dataProcess.getDataAll();
		model.addAttribute("datas", list);
		return "list";
	}

리스트를 보여달라는 요청에 따라 전체 데이터를 보여주자. 

 

@Repository
public class DataProcess {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private DataMapperInterface dataMapperInterface; //hikari pool이 자동지원
	
	//전체자료읽기
	public List<MemDto> getDataAll(){
		List<MemDto> list = dataMapperInterface.selectAll();
		logger.info("전체자료 크기: "+ list.size());//syso대신
		return list;
	}

private Logger logger = LoggerFactory.getLogger(this.getClass());

logger.info("전체자료 크기: "+ list.size());

 

Logger 객체를 생성해주었다. 이 객체는 Java의 로깅 프레임워크인 SLF4J(Simple Logging Facade for Java)를 사용하여 애플리케이션의 로깅을 관리해준다. 

System.out.println();대신 logger.info 로 콘솔에 출력하고자 코드를 추가했다.

 

@Mapper
public interface DataMapperInterface {
	@Select("select * from mem")
	List<MemDto> selectAll();

Mybatis는 복수일경우 반드시 list로 반환해준다. not Arraylist.

 

<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>templates/list.html</title>
</head>
<body>
<h2>🍇회원목록(@MVC MyBatis)🍇</h2>
<a th:href="@{/insert}">추가</a>

<table border="1">

<tr>
	<th>번호</th><th>이름</th><th>주소</th><th>수정/삭제</th>
</tr>
<th:block th:if="${datas.size > 0}">
<tr th:each="data:${datas}"> <!-- datas가 가진값을 data로 하나씩 뽑아낸다 -->
	<td>[[${data.num}]]</td>
	<td>[[${data.name}]]</td>
	<td>[[${data.addr}]]</td>
	<td>
	<a th:href="@{/update(num=${data.num})}">수정/</a>
	<a th:href="@{/delete(num=${data.num})}">삭제</a>
	</td>
</tr>
</th:block>
</table>
<br>
<a th:href="@{/}">메인으로</a>
</body>
</html>

 

추가하기

list.html에서 추가하기 링크로 추가해보자.

@GetMapping("insert")
	public String insert() {
		return "insert";
	}
<title>templates/insert.html</title>
</head>
<body>
<h3>🥦자료 입력🥦</h3>
<form th:action="@{/insert}" method="post">
번호 : <input type="text" name="num"><br>
이름 : <input type="text" name="name"><br>
주소 : <input type="text" name="addr"><br>
<br>
<input type="submit" value="등록">
</form>

@PostMapping("insert")
	public String insertProcess(MemBean bean) {
		boolean b = dataProcess.insert(bean);
		if(b)
			return "redirect:/list";
		else 
			return "redirect:/error";
	}
    
    @GetMapping("error")
	public String error() {
		return "error";
	}
//추가하기 추가시 0아니면1
	public boolean insert(MemBean bean) {
		//번호중복방지, 번호자동증가 는 추가작업.
		int re = dataMapperInterface.insertData(bean);
		if(re >0)//즉 =1이면 성공. 아니면 false
			return true;
		else 
			return false;	
	}
	@Insert("insert into mem values(#{num}, #{name}, #{addr})")
	int insertData(MemBean bean);
<title>templates/error.html</title>
</head>
<body>
에러발생!! <hr>
<a th:href="@{/list}">회원목록 보기</a>
</body>

 

수정하기

@GetMapping("update")
	public String update(@RequestParam("num") String num, Model model) {
		MemDto dto = dataProcess.getData(num);
		model.addAttribute("data", dto); //=request.setAttribute
		return "update";
	}

수정할 부분자료를 읽어야한다.

//부분자료읽기
	public MemDto getData(String num) {
		MemDto dto = dataMapperInterface.selectPart(num);
		return dto;
	}
	@Select("select * from mem where num=#{num}")
	MemDto selectPart(String num);
<h3>🥦자료 수정🥦</h3>
<form th:action="@{/update}" method="post" th:object="${data}">
<!-- th:object로 값 받아서, ${data.num}로 뿌린다. 넘길땐 field * 로 넘긴다. -->
번호 : <span th:text="${data.num}">번호</span><br>
<input type="hidden" th:field="*{num}">
<!-- 번호는 수정에서 제외. 보여만준다. 가지고 가야하기에, hidden으로 번호를 넘긴다. -->
이름 : <input type="text" th:field="*{name}"><br>
주소 : <input type="text" th:field="*{addr}"><br>
<br>
<input type="submit" value="수정">
</form>

 

 

th: object, *, th:field

입력 폼 처리

th:object, *{...}, th:field 3개를 함께 사용하면 <form>을 편리하게 작성할 수 있다.

  • th:object: 커맨드 객체를 지정한다.
    • 단, 해당 오브젝트 정보를 model에 담아서 넘겨주어야 한다.
    • 등록 폼이기 때문에 데이터가 비어있는 빈 오브젝트를 만들어서 뷰에 전달한다.
  • *{...}: th:object에서 선택한 객체에 접근한다.
    • ${객체.필드}와 같다.
    • th:object=${객체명}+*{필드명} 을 사용하던지, ${객체.필드}를 사용하던지 선택하면 된다.
      • 하위 태그에 객체 접근 할 일이 많다면 전자가 편리할것.
  • th:field: HTML 태그의 id, name, value 속성을 자동으로 만들어준다.
    • input에 적용하는 필드이다.
    • id와 name은 th:field에서 지정한 변수 이름과 같게 만들어진다.
      • <label>등과 함께 사용시 id가 존재하지 않으면 ide측에서 오류로 간주한다. (타임리프는 렌더링시 만들어주기 때문). 따라서 필요할 시에는 id를 직접 적어야한다.
    • value는 th:field에서 지정한 변수의 값(model에 담긴 값)을 사용한다.

이러면 페이지소스코드에서 볼때 자동으로 생성된다.

 

 

읽어온 자료를 수정해서 새로운 정보를 입력하자.

	@PostMapping("update")
	public String updateProcess(MemBean bean) {
		boolean b = dataProcess.update(bean);
		if(b)
			return "redirect:/list";
		else 
			return "redirect:/error";
	}
	@Update("update mem set name=#{name}, addr=#{addr} where num=#{num}")
	int updateData(MemBean bean);

이름을 초록색 > 마이클로 변경했다.

 

삭제하기

@GetMapping("delete")
	public String delete(@RequestParam("num") String num) {
		boolean b = dataProcess.delete(num);
		if(b)
			return "redirect:/list";
		else 
			return "redirect:/error";
	}
//삭제하기
	public boolean delete(String num) {
		//번호중복방지, 번호자동증가 는 추가작업.
		int re = dataMapperInterface.deleteData(num);
		if(re >0)//즉 =1이면 성공. 아니면 false
			return true;
		else 
			return false;	
	}
@Delete("delete from mem where num=#{num}")
	int deleteData(String num);

마이클 삭제 완료.

 

전체 소스코드는 깃허브의 sprweb11,12를 참고하자.

https://github.com/yoonah0327/spring_source.git

 

GitHub - yoonah0327/spring_source

Contribute to yoonah0327/spring_source development by creating an account on GitHub.

github.com

 

 


https://hanke-r.tistory.com/70

 

Spring boot - application.properties MySQL DB 설정

pom.xml mysql mysql-connector-java # MySQL8 설정 spring.datasource.url=jdbc:mysql://localhost:3306/스키마명?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC spring.datasource.username=아이디 spring.datasource.password=비밀번호 spring.da

hanke-r.tistory.com

https://velog.io/@gmtmoney2357/%ED%83%80%EC%9E%84%EB%A6%AC%ED%94%84Thymeleaf-%EA%B8%B0%EB%B3%B8%EA%B8%B0%EB%8A%A56

 

타임리프(Thymeleaf) - 기본기능6

th:object, \*{...}, th:field 3개를 함께 사용하면 <form>을 편리하게 작성할 수 있다.th:object: 커맨드 객체를 지정한다.단, 해당 오브젝트 정보를 model에 담아서 넘겨주어야 한다.등록 폼이기 때문에 데이

velog.io