<body>
<div>
<form action="list" class="d-inline-flex">
<select name="title" class="form-control">
<option value="name" ${title=="name"?"selected":"" }>이름</option>
<option value="addr" ${title=="addr"?"selected":"" }>주소</option>
<option value="driver" ${title=="driver"?"selected":"" }>운전면허</option>
</select>
<input type="text" name="search" class="form-control" placeholder="검색" value="${search }">
<button type="submit" class="btn btn-success">검색</button>
</form>
</div>
</body>
<?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="friday">
<!-- 검색 리스트 -->
<select id="selectAllInfo" resultType="idto" parameterType="Map">
select * from myinfo
<if test="search!=null">
where ${title} like concat('%',#{search},'%') <!-- where {검색기준이 될 필드명} like concat('%',?,'%'); -->
</if> <!-- ${컬럼자체},#{데이터} -->
order by num desc
</select>
</mapper>
@Repository
public class InfoDao implements InfoInter {
@Autowired
SqlSession session;
@Override
public List<InfoDto> getAllInfo(Map<String, String> map) {
return session.selectList("selectAllInfo", map);
}
}
@Controller
public class InfoController {
@Autowired
InfoInter inter;
//getTotalCount(),getAllInfo() 생략..1013참조
@GetMapping("/info/list")
public String list(Model model,
@RequestParam(defaultValue = "name") String title,
@RequestParam(required = false) String search) {
int count=inter.getTotalCount();
//List<InfoDto> list=inter.getAllInfo();
System.out.println(title+","+search);
Map<String, String> map=new HashMap<String, String>();
map.put("search", search);
map.put("title", title);
List<InfoDto> list=inter.getAllInfo(map);
model.addAttribute("count", count);
model.addAttribute("list", list);
model.addAttribute("search", search);
model.addAttribute("title", title);
return "info/infoList";
}
}
<!--servlet-context.xml-->
<beans>
<context:component-scan base-package="spring.mvc.*,board.data.controller" />
</beans>
create table reboard(num smallint primary key auto_increment,
writer varchar(20),
pass varchar(20),
subject varchar(200),
content varchar(2000),
photo varchar(500),
regroup smallint,
restep smallint,
relevel smallint,
viewcount smallint default 0,
writeday datetime);
public class BoardDto {
private int num;
private int regroup;
private int restep;
private int relevel;
private int viewcount;
private String writer;
private String pass;
private String subject;
private String content;
private String photo;
private Timestamp writeday;
//getter,setter 생략
}
<!--mybatis-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="bdto" type="spring.mvc.reboard.BoardDto"/>
</typeAliases>
</configuration>
public interface BoardDaoInter {
public int getTotalCount();
public int getMaxNum();
public void updateRestep(int regroup,int restep); //댓글 출력 제어용
public void insertReboard(BoardDto dto);
public List<BoardDto> getPagingList(int start,int perPage);
public BoardDto getContent(int num);
}
--mysql in spring
select ifnull(max(num),0) from reboard --null값 처리..ifnull()
g = g (대상 글과 동일한 group)
s’ = s+1 그리고 해당 group에 속하는 게시물의 s 값 중 s’ 이상은 모두 s = s+1 (첨부 대상 글보다 순서 값 증가하되, 다른 게시물 사이에 생성될 경우 이후의 게시물 순서 차례로 밀어내기)
--mysql in spring
update reboard set restep=restep+1 where regroup=#{regroup} and restep>#{restep}
l = l+1 (첨부 대상 글보다 1 계층 아래)
<?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="board">
<select id="getTotalCountOfReboard" resultType="int">
select count(*) from reboard
</select>
<!-- num의 max값,null일경우 0 -->
<select id="maxNumOfReboard" resultType="int">
select ifnull(max(num),0) from reboard
</select>
<!-- 같은 그룹중에서 step보다 큰데이터는 모두 +1 -->
<update id="updateStepOfReboard" parameterType="HashMap">
update reboard set restep=restep+1 where regroup=#{regroup} and restep>#{restep}
</update>
<!-- insert: 새글,답글 모두 해당 -->
<insert id="insertOfReboard" parameterType="bdto">
insert into reboard (writer,pass,subject,content,photo,regroup,restep,relevel,writeday)
values (#{writer},#{pass},#{subject},#{content},#{photo},#{regroup},#{restep},#{relevel},now())
</insert> <!--viewcount는 default 0이므로 null-->
<!-- 페이징처리 전체리스트 -->
<select id="selectPagingOfReboard" resultType="bdto" parameterType="HashMap">
select * from reboard order by regroup desc,restep asc limit #{start},#{perPage}
</select>
<select id="selectContent" resultType="bdto" parameterType="int">
select * from reboard where num=#{num}
</select>
</mapper>
@Repository
public class BoardDao implements BoardDaoInter {
@Autowired
private SqlSession session;
//getTotalCount(),getMaxNum() 생략
@Override
public void updateRestep(int regroup, int restep) {
Map<String, Integer> map=new HashMap<String, Integer>();
map.put("regroup", regroup);
map.put("restep", restep);
session.update("updateStepOfReboard", map);
}
}
@Repository
public class BoardDao implements BoardDaoInter {
//sqlSession 생성 및 연결 생략
@Override
public void insertReboard(BoardDto dto) {
int num=dto.getNum(); //String이면 null이냐 아니냐,int면 0이냐 아니냐
int regroup=dto.getRegroup();
int restep=dto.getRestep();
int relevel=dto.getRelevel();
if(num==0) {
regroup=getMaxNum()+1;
restep=0;
relevel=0;
}
else {
//같은 그룹중 잔달받은 restep보다 큰글들은 모두 +1
this.updateRestep(regroup, restep);
//전달받은 step과 level 모두 +1
restep++;
relevel++;
}
//바뀐값들을 다시 dto에 담는다
dto.setRegroup(regroup);
dto.setRestep(restep);
dto.setRelevel(relevel);
session.insert("insertOfReboard", dto);
}
}
@Repository
public class BoardDao implements BoardDaoInter {
@Override
public List<BoardDto> getPagingList(int start, int perPage) {
Map<String, Integer> map=new HashMap<String, Integer>();
map.put("start", start);
map.put("perPage", perPage);
return session.selectList("selectPagingOfReboard", map);
}
}
@Repository
public class BoardDao implements BoardDaoInter {
@Override
public BoardDto getContent(int num) {
return session.selectOne("board.selectContent", num);
}
}
@Controller
public class BoardListController {
@Autowired
BoardDaoInter dao;
@GetMapping("board/list")
public String list(Model model,
@RequestParam(value = "currentPage",defaultValue = "1") int currentPage) {
//페이징처리에 필요한 변수선언
int totalCount=dao.getTotalCount();
int totalPage; //총 페이지수
int startPage; //각블럭에서 보여질 시작페이지
int endPage; //각블럭에서 보여질 끝페이지
int startNum; //db에서 가져올 글의 시작번호(mysql은 첫글이 0,오라클은 1)
int perPage=3; //한페이지당 보여질 글의 갯수
int perBlock=5; //한블럭당 보여질 페이지 개수
totalPage=totalCount/perPage+(totalCount%perPage==0?0:1);
startPage=(currentPage-1)/perBlock*perBlock+1;
endPage=startPage+perBlock-1;
if(endPage>totalPage)
endPage=totalPage;
startNum=(currentPage-1)*perPage;
//각페이지에서 필요한 게시글 가져오기
List<BoardDto> list=dao.getPagingList(startNum, perPage);
//각 페이지에 출력할 시작번호
int no=totalCount-startNum;
model.addAttribute("totalCount", totalCount);
model.addAttribute("list", list);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);
model.addAttribute("totalPage", totalPage);
model.addAttribute("no", no);
model.addAttribute("currentPage", currentPage);
return "reboard/boardList";
}
}
@Controller
public class BoardWriteController {
@Autowired
BoardDaoInter dao;
@GetMapping("/board/writeForm")
public String writeform(Model model,@RequestParam Map<String, String> map) {
//요 5개는 답글일 경우에만 넘어온다(새글일경우 안넘어옴)
String currentPage=map.get("currentPage");
String num=map.get("num");
String regroup=map.get("regroup");
String restep=map.get("restep");
String relevel=map.get("relevel");
System.out.println(currentPage+","+num);
//입력폼에 hidden으로 넣어줘야함..답글일때 대비
model.addAttribute("currentPage", currentPage==null?"1":currentPage);
model.addAttribute("num", num==null?"0":num);
model.addAttribute("regroup", regroup==null?"0":regroup);
model.addAttribute("restep", restep==null?"0":restep);
model.addAttribute("relevel", relevel==null?"0":relevel);
//dao설정에 따라 디폴트값 0으로..0으로 넣어야 dao에서 새글로 인식
//폼이 답글,새글 공용이므로
return "reboard/writeForm";
}
}
@Controller
public class BoardWriteController {
@Autowired
BoardDaoInter dao;
@PostMapping("/board/insert")
public String insert(@ModelAttribute BoardDto dto,
@RequestParam ArrayList<MultipartFile> uimage, //업로드 파일 여러개라서
HttpSession session) {
String path=session.getServletContext().getRealPath("/WEB-INF/photo");
System.out.println(path);
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
String photo="";
if(uimage.get(0).getOriginalFilename().equals(""))
photo="no";
else {
for(MultipartFile f:uimage) {
String fName=sdf.format(new Date())+"_"+f.getOriginalFilename();
photo+=fName+",";
try {
f.transferTo(new File(path+"\\"+fName));
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//photo에서 마지막 컴마 제거
photo.substring(0, photo.length()-1);
}
//dto의 photo에 넣기
dto.setPhoto(photo);
//insert
dao.insertReboard(dto);
return "redirect:list"; //content일단 없으니까 목록으로
}
}
<body>
<div>
<table>
<caption align="top"><b>스프링 답변형 게시판</b>
<span style="float: right">
<button type="button" class="btn btn-outline-info" onclick="location.href='writeForm'">글쓰기</button>
</span>
</caption>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회</th>
</tr>
<c:if test="${totalCount==0 }">
<tr>
<td colspan="5" align="center"><b>등록된 게시글이 없습니다</b></td>
</tr>
</c:if>
<c:if test="${totalCount>0 }">
<c:forEach var="dto" items="${list }">
<tr>
<td align="center">${no }</td>
<c:set var="no" value="${no-1 }"></c:set> <!-- 출력후 감소(증감연산자 없음) -->
<td> <!-- 제목 -->
<!-- relevel만큼 공백 -->
<c:forEach var="s" begin="1" end="${dto.relevel }">
</c:forEach>
<!-- 답글인 경우에만 re.png이미지출력 -->
<c:if test="${dto.relevel>0 }">
<img src="../upload/re.png">
</c:if>
<!-- 제목..여기누르면 내용보기로 -->
<a href="content?num=${dto.num }¤tPage=${currentPage}">${dto.subject }</a>
<!-- 사진이 있을경우 아이콘 표시 -->
<c:if test="${dto.photo!='no' }">
<i class="bi bi-images"></i>
</c:if>
</td>
<td align="center">${dto.writer }</td>
<td align="center"><fmt:formatDate value="${dto.writeday }" pattern="yyyy-MM-dd"/></td>
<td align="center">${dto.viewcount }</td>
</tr>
</c:forEach>
</c:if>
</table>
<!--페이징 처리 생략-->
</div>
</body>
<!-- 페이징 -->
<c:if test="${totalCount>0 }">
<div>
<ul class="pagination justify-content-center">
<!-- 이전 -->
<c:if test="${startPage>1 }">
<li class="page-item"><a href="list?currentPage=${startPage-1 }">이전</a></li>
</c:if>
<c:forEach var="pp" begin="${startPage }" end="${endPage }">
<c:if test="${pp==currentPage }">
<li class="page-item active">
<a class="page-link" href="list?currentPage=${pp }">${pp }</a>
</li>
</c:if>
<c:if test="${pp!=currentPage }">
<li class="page-item">
<a class="page-link" href="list?currentPage=${pp }">${pp }</a>
</li>
</c:if>
</c:forEach>
<!-- 다음 -->
<c:if test="${endPage<totalPage }">
<li class="page-item"><a href="list?currentPage=${endPage+1 }">다음</a></li>
</c:if>
</ul>
</div>
</c:if>
1017에 이어서 to be continued