도출해내야하는 결과
1. 이름과 성별, 주민등록번호, 거주시/도를 입력했을때 DB 에 성공적으로 insert 됐을시 '데이터를 성공적으로 추가하였습니다'라는 화면창에 띄우기
2. 카테고리에서 이름, 성별, 주민등록 번호, 거주 시/도를 검색했을때 그 검색값에 맞게 게시글이 나와야한다.
3. 주민등록 번호 같은경우는 앞자리만 검색해도 뒷자리까지 같이 검색결과 게시글로 나와야한다.
1. `test0426`.`personals`테이블 만들기
```
CREATE SCHEMA `test0426`;
CREATE TABLE `test0426`.`personals`
(
`name` VARCHAR(10) NOT NULL, //이름
`gender` VARCHAR(1) NOT NULL, //성별
`ssn_birth` VARCHAR(6) NOT NULL, //첫번째 칸 주민번호
`ssn_key` VARCHAR(7) NOT NULL, //두번째 칸 주민번호
`region` VARCHAR(10) NOT NULL, //지역 이름
CONSTRAINT PRIMARY KEY (`ssn_birth`, `ssn_key`)//주민번호 칸 프라이머리키 해보기
);
```
2. html 만들어주기
```
<form method="post"> <!--form 메서드에서 post 를 지정해줘야함-->
<h2 class="title">주민관리</h2>
<div class="horizontal">
<label class="label">
<span class="text">이름</span>
<input maxlength="10" minlength="2" name="name" spellcheck="false" type="text" placeholder="성/이름(공백없이)">
</label>
<br>
<label class="label" content>
<span class="text">성별</span>
<select nam e="gender">
<option value="M">남</option>
<option value="F">여</option>
</select>
</label>
<br>
<label class="label" content>
<span class="text">주민등록번호</span>
<input maxlength="6" minlength="6" name="ssnBirth" spellcheck="true" type="text" placeholder="앞자리(숫자 여섯자리)">
</label>
<label class="label" content>
<span class="text"></span>
<input maxlength="7" minlength="7" name="ssnKey" spellcheck="true" type="text" placeholder="뒷자리(숫자 일곱 자리)">
</label>
<br>
<label class="label" content>
<span class="text">거주 시/도</span>
<select name="region"> //option value 값으로 DB에 들어감
<option value="서울특별시">서울특별시</option>
<option value="부산광역시">부산광역시</option>
<option value="대구광역시">대구광역시</option>
<option value="인천광역시">인천광역시</option>
<option value="광주광역시">광주광역시</option>
<option value="대전광역시">대전광역시</option>
<option value="울산광역시">울산광역시</option>
<option value="세종특별자치시">세종특별자치시</option>
<option value="경기도">경기도</option>
<option value="강원특별자치도">강원특별자치도</option>
<option value="충청북도">충청북도</option>
<option value="충청남도">충청남도</option>
<option value="전북특별자치도">전북특별자치도</option>
<option value="전라남도">전라남도</option>
<option value="경상북도">경상북도</option>
<option value="경상남도">경상남도</option>
<option value="제주특별자치도">제주특별자치도</option>
</select>
</label>
<br>
<input class="button" type="submit" value="추가">
<!--버튼을 누르면 post 로 요청이 들어간다.-->
</div>
<div class="true" th:if="${result != null && result.equals('SUCCESS')}" th:text="${'메모를 성공적으로 작성하였습니다.'}"></div>
<div class="false" th:if="${result != null && result.equals('FAILURE')}" th:text="${'메모 작성을 실패하였습니다. '}"></div>
</form>
```
```
<td colspan="5"> <!--4칸을 합쳐서 페이지를 보여주겠다.-->
<a th:each="page:${#numbers.sequence(dto?.getMinPage(), dto?.getMaxPage())}"
th:href="@{/personal/(page=${page})}" // personal은 맵핑할 주소를 적어줘야한다.
th:text="${page}" style="display: inline-block; margin-right: 10px;"></a>
<!-- page 는 반복문 돌릴때 사용되는 변수이름이다.
th:href="@{/personal/(page=${page})}" 맵핑 주소 적어줘야함 -->
</td>
```
- <th:href="@{/personal/(page=${page})}" >
<오류 떴던 이유>
- 여기에서 주소창에 맵핑한 주소 /personal/을 적어줘야하는데 memos 를 적어줘서 페이지 눌렀을때 404가 떴던거였음 .
3. 검색창에 쳤을때 나오는 html
- 여기서 form method는 get 으로 맞춰줘야한다.
- select name과 value 값을 xml에서 매개변수를 쓸때 똑같이 잘 써주지 않으면 검색했을때 결과값이 나오지 않으므로 주의
- 여기서 parameterType으로 countPerPage랑 offset을 사용해주고 있기때문에 MemoDto를 연결해주고 resultType으로 PersonEntity를 꼭 연결시켜줘여한다.
- resultType 은 xml에서 자바로 반환되는 결과타입을 적어줘야함
- resultType 속성에는 기본 데이터 타입(int, long, double, boolean 등)과 자바 클래스(String, Date, User 등)를 모두 사용할 수 있습니다.
- parameterType 은 어떤 곳에서 매개변수를 쓸것인가 주소를 적어줘야함
- 기본 데이터 타입(int, long, double, boolean 등)과 자바 클래스(String, Date, User 등)를 모두 사용할 수 있습니다.
4. interface 에 추가해주기
```
int insertPerson(PersonEntity person);//화면창에 기입한정보를 DB에 넣어줄 인터페이스
PersonEntity[] allSelect (MemoDto dto);//페이지 가져오는 메서드
```
4. MemoMapper.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="cohttp://m.jjrr.study.mappers.MemoMapper" >
<select id="selectPage" resultType="_int" parameterType="cohttp://m.jjrr.study.dto.MemoDto">
SELECT COUNT(0) AS `count`
FROM `test0426`.`personals`
<if test="by != null and by.equals('name') and keyword != null">
WHERE REPLACE(`name`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('gender') and keyword != null">
WHERE REPLACE(`gender`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('person') and keyword != null">
WHERE CONCAT(REPLACE(`ssn_birth`, ' ', ''), REPLACE(`ssn_key`, ' ', '')) LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('region') and keyword != null">
WHERE REPLACE(`region`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
</select>
---
<insert id="insertPerson" parameterType="cohttp://m.jjrr.study.entity.PersonEntity">
INSERT INTO test0426.personals(`name`, `gender`, `ssn_birth`, `ssn_key`, `region`)
VALUES (`#{name},#`{gender},`#{ssnBirth},#`{ssnKey},#{region})
</insert>
---
<select id="allSelect" parameterType="cohttp://m.jjrr.study.dto.MemoDto" resultType="cohttp://m.jjrr.study.entity.PersonEntity">
SELECT
`personals`.`name` AS `name`,
`personals`.`gender` AS `gender`,
`personals`.`ssn_birth` AS `ssnBirth`,
`personals`.`ssn_key` AS `ssnKey`,
`personals`.`region` AS `region`
FROM `test0426`.`personals`
<if test="by != null and by.equals('name') and keyword != null">
WHERE REPLACE(`name`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('gender') and keyword != null">
WHERE REPLACE(`gender`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('person') and keyword != null">
WHERE CONCAT(REPLACE(`ssn_birth`, ' ', ''), REPLACE(`ssn_key`, ' ', '')) LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="by != null and by.equals('region') and keyword != null">
WHERE REPLACE(`region`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
LIMIT #{countPerPage} OFFSET #{offset}
</select>
</mapper>
`
- 이 쿼리에서 if문을 쓸때 주민번호는 앞자리만 나 뒷자리만 쳐도 검색 결과가 나와야하기 떄문에 if문을 따로 쓰면 안되고 한번에 써줘야 같이 나온다.
- CONCAT :이 함수는 여러 개의 문자열을 하나의 문자열로 결합하는 기능
- REPLACE : 이 함수는 문자열 내에서 특정 문자열을 다른 문자열로 대체하는 기능을 합니다.
- WHERE : WHERE 절을 사용하면 테이블에서 특정 조건에 맞는 데이터만 선택할 수 있습니다.
- **WHERE REPLACE(****region****, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')**
region 컬럼의 값에서 공백을 제거한 후, 사용자 입력 키워드(공백 제거 후)를 포함하고 있는지 확인합니다.
이를 통해 region 컬럼의 값과 사용자 입력 키워드 간의 부분 일치 검색을 수행할 수 있습니다
서비스 로직
```
@Service
public class MemoService {
public final MemoMapper memomapper;
public MemoService(MemoMapper mapper) { //서비스 메퍼랑 의존성 추가해주기
this.memomapper = mapper;
}
/* 주민번호 DB에 insert 하는 메서드 */
public AddResult add(PersonEntity person){
if (person == null || person.getGender() == null || person.getRegion()==null||person.getSsnKey().length() != 7 || person.getSsnBirth().length() != 6 || person.getName().length() >10||person.getName().length() < 2){
return AddResult.FAILURE;
}
int db = this.memomapper.insertPerson(person);
return db > 0 ? AddResult.SUCCESS: AddResult.FAILURE;
}
public PersonEntity[] getMemo(MemoDto dto) { // 전체게시물을 보여줘야하기때문에 꼭 배열로 가져와줘야함
dto.setCountPerPage(5);//한페이지당 몇개 게시글 보여줄것인지
dto.setTotalCount(this.memomapper.selectPage(dto)); // 전체 게시글 숫자 넣어주기
dto.setMaxPage(dto.getTotalCount() / dto.getCountPerPage() + (dto.getTotalCount() % dto.getCountPerPage() == 0 ? 0 : 1));
if (dto.getMaxPage()<1){
dto.setMaxPage(1); //최대페이지수가 1보다 작을때 0이라고 뜨는걸 방지하기 위해 기입함
}
dto.setOffset(dto.getCountPerPage() * (dto.getRequestPage()-1));
//거를 게시글 갯수
//한페이지당 보여줄 게시글수 X 요청페이지-1
// 이렇게 해야 1페이지에 있는 5개 게시글 빼고 노출되기 때문이다.
dto.setMinPage(1); //젤 작은 페이지수는 1페이지로 지정
System.out.println(dto.getKeyword());
return memomapper.allSelect(dto);
}
}
게시판 만들기 2(검색기능 추가하기) (0) | 2024.05.07 |
---|---|
게시판 만들기1 (기초) (0) | 2024.05.07 |