@Entity
@Data
@SequenceGenerator(name = "SEQ_BOARD_NO", sequenceName = "SEQ_BOARD_NO", initialValue = 1, allocationSize = 1)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_BOARD_NO")
@Column(name = "NO")
private long no;
private String title;
@Lob
private String content;
private String writer;
private long hit;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
@CreationTimestamp
private Date regdate;
}
entity에 board.java를 생성한다.
이미 테이블을 만들었기 때문에 application.properties에서 update로 변경하지 않아도 된다.
[no] in table [board]; found [decfloat (Types#NUMERIC)], but expecting [bigint (Types#BIGINT)]
서버를 실행하면 위 오류가 뜰 것이다.
이럴 때는
private BigDecimal no;
private BigDecimal hit;
Board.java를 위 코드로 수정한다.
@Slf4j
@Controller
@RequestMapping(value = "/board2")
@RequiredArgsConstructor
public class Board2Controller {
final Board2Repository bRepository; // 저장소 객체
// 127.0.0.1:9090/ROOT/board2/selectlist.pknu
@GetMapping(value="/selectlist.pknu")
public String selectListGET(Model model){
try{
List<Board> list = bRepository.findAll();
model.addAttribute("list", list);
return "/board2/selectlist";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
}
Board2Controller.java를 생성하여 selectListGET을 작성하고
<body>
<h3>목록(board)</h3>
<a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
<hr />
<table>
<tr th:each="obj : ${list}">
<td><input type="checkbox" /></td>
<td th:text="${obj.no.longValue()}"></td>
<td th:text="${obj.title}"></td>
<td th:text="${obj.writer}"></td>
<td th:text="${obj.hit.longValue()}"></td>
<td th:text="${obj.regdate}"></td>
</tr>
</table>
</body>
selectlist.html을 만든 후
@Repository
public interface Board2Repository extends JpaRepository<Board, Long> {
}
Board2Repository를 생성한다.
이렇게 나온다.
// select * from board order by no desc
List<Board> findAllByOrderByNoDesc();
Board2Repository.java에 위 코드를 추가하고
try{
List<Board> list = bRepository.findAllByOrderByNoDesc();
model.addAttribute("list", list);
return "/board2/selectlist";
}
Board2Controller를 위처럼 수정한다.
내림차순으로 변경된 것을 확인할 수 있다.
@GetMapping(value="/insertbatch.pknu")
public String insertbatchGET(Model model){
try{
return "/board2/insertbatch";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java에 insertbatchGET을 추가하고
<body>
<h3>일괄추가</h3>
<a th:href="@{/board2/selectlist.pknu}"><button>목록으로</button></a>
<hr />
<form th:action="@{/board2/insertbatch.pknu}" method="post">
<th:block th:each="i : ${#numbers.sequence(1,3)}">
<input type="text" name="title[]" th:value="|t_${i}|" />
<input type="text" name="content[]" th:value="|c_${i}|"/>
<input type="text" name="writer[]" th:value="|w_${i}|"/>
<br />
</th:block>
<input type="submit" value="일괄추가" />
</form>
</body>
insertbatch.html을 추가한다.
게시글목록에서 일괄추가 버튼을 누르면 이렇게 일괄추가할 수 있는 창이 생성된다.
@PostMapping(value="/insertbatch.pknu")
public String insertBatchPOST(
@RequestParam( name = "title[]") String[] title,
@RequestParam( name = "content[]") String[] content,
@RequestParam( name = "writer[]") String[] writer){
try{
List<Board> list = new ArrayList<>();
for(int i = 0; i<title.length; i++){
Board board = new Board();
board.setTitle(title[i]);
board.setContent(content[i]);
board.setWriter(writer[i]);
board.setHit(BigDecimal.valueOf(1));
list.add(board);
}
bRepository.saveAll(list);
return "redirect:/board2/selectlist.pknu";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java에 insertBatchPOST를 추가한다.
일괄추가를 누르면
이렇게 t_1 ~ t_3 까지 추가가 된다.
public interface Board2Repository extends JpaRepository<Board, BigDecimal>
Board2Repository에서 Long => BigDecimal로 수정한다
@PostMapping(value="/deletebatch.pknu")
public String deleteBatchPOST(
@RequestParam(name="chk[]") List<BigDecimal> chk){
try{
log.info(chk.toString());
bRepository.deleteAllById(chk);
return "redirect:/board2/selectlist.pknu";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java에 deleteBatchPOST를 추가한다.
<body>
<h3>목록(board)</h3>
<a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
<button th:onclick="formAction1(1)">일괄수정</button>
<button th:onclick="formAction1(2)">일괄삭제</button>
<hr />
<form th:action="@{/board2/updatebatch.pknu}" method="post" id="form">
<table border="1">
<tr th:each="obj : ${list}">
<td><input type="checkbox" name="chk[]" th:value="${obj.no.longValue()}"/></td>
<td th:text="${obj.no.longValue()}"></td>
<td th:text="${obj.title}"></td>
<td th:text="${obj.writer}"></td>
<td th:text="${obj.hit.longValue()}"></td>
<td th:text="${obj.regdate}"></td>
</tr>
</table>
</form>
<script th:inline="javascript" type="text/javascript">
function formAction1(code) {
const form = document.getElementById('form');
if(code === 1) {
form.action = /*[[@{/board2/updatebatch.pknu}]]*/'';
}
else if(code === 2) {
form.action = /*[[@{/board2/deletebatch.pknu}]]*/'';
}
form.submit();
}
</script>
</body>
selectlist.html을 위 코드처럼 수정, 추가한다.
2개를 체크하고 일괄삭제를 누르면
이렇게 삭제된 것을 볼 수 있다.
final HttpSession httpSession; // 세션객체
@PostMapping(value="/updatebatchaction.pknu")
public String updatePOST(
@RequestParam( name = "no[]") long[] no,
@RequestParam( name = "title[]") String[] title,
@RequestParam( name = "content[]") String[] content,
@RequestParam( name = "writer[]") String[] writer){
try{
List<Board> list = new ArrayList<>();
for(int i=0; i<no.length; i++){
// 1. no를 이용하여 기존 정보 가져오기
Board board = bRepository.findById(BigDecimal.valueOf(no[i])).orElse(null);
// 2. 기존정보에 위에서 받은 제목, 내용, 작성자 변경하기
board.setTitle(title[i]);
board.setContent(content[i]);
board.setWriter(writer[i]);
// 3. list에 담기
list.add(board);
}
// 4. 일괄 저장하기
bRepository.saveAll(list);
return "redirect:/board2/selectlist.pknu";
} catch(Exception e){
return "redirect:/home.do";
}
}
@SuppressWarnings("unchecked")
@GetMapping(value="/updatebatch.pknu")
public String updateBatchGET(Model model){
try{
List<BigDecimal> chk = (List<BigDecimal>) httpSession.getAttribute("chk[]");
List<Board> list = bRepository.findAllById(chk);
model.addAttribute("list", list);
return "/board2/updatebatch";
} catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
@PostMapping(value="/updatebatch.pknu")
public String updateBatchPOST(@RequestParam(name="chk[]") List<BigDecimal> chk){
try{
httpSession.setAttribute("chk[]", chk);
return "redirect:/board2/updatebatch.pknu";
} catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java에 updateBatchGET, updateBatchPOST, updatePOST를 추가하고
<body>
<h3>일괄수정(board)</h3>
<a th:href="@{/board2/selectlist.pknu}"><button>목록으로</button></a>
<hr />
<form th:action="@{/board2/updatebatchaction.pknu}" method="post">
<table>
<tr th:each="obj : ${list}">
<td><input type="text" name="no[]" th:value="${obj.no.longValue()}" readonly/></td>
<td><input type="text" name="title[]" th:value="${obj.title}" /></td>
<td><input type="text" name="content[]" th:value="${obj.content}" /></td>
<td><input type="text" name="writer[]" th:value="${obj.writer}" /></td>
<td><input type="text" th:value="${obj.hit.longValue()}" readonly/></td>
<td><input type="text" th:value="${obj.regdate}" readonly/></td>
</tr>
</table>
<input type="submit" value="일괄수정" />
</form>
</body>
updatebatch.html을 생성하여 작성한다.
43~45를 선택하고 일괄수정을 누르면
updatebatch.pknu로 이동한다.
여기서 no, hit, regdate는 readonly이므로 수정할 수 없다.
이렇게 수정하고 일괄수정을 누르면
이렇게 바뀐 모습을 볼 수 있다.
// 3. 검색어 타입에 따른 메소드 3개 만들기
// select * from board where title like '%' || ? || '%' order by no desc
List<Board> findByTitleIgnoreCaseContainingOrderByNoDesc(String title);
List<Board> findByContentIgnoreCaseContainingOrderByNoDesc(String content);
List<Board> findByWriterIgnoreCaseContainingOrderByNoDesc(String writer);
List<Board> findByTitleIgnoreCaseContainingOrderByNoDesc(String title, Pageable pageable);
List<Board> findByContentIgnoreCaseContainingOrderByNoDesc(String content, Pageable pageable);
List<Board> findByWriterIgnoreCaseContainingOrderByNoDesc(String writer, Pageable pageable);
Board2Repository.java에 위 코드를 추가하고
// 127.0.0.1:9090/ROOT/board2/selectlist.pknu
// 1. 전달값 받기 ?page=1&type=writer&text=~~~
@GetMapping(value="/selectlist.pknu")
public String selectListGET(Model model,
@RequestParam(name="page", defaultValue = "1") int page,
@RequestParam(name="type", defaultValue = "title") String type,
@RequestParam(name="text", defaultValue = "") String text ){
try{
// 2. 타입에 따라서 다른 메소드 호출
// findByTitle...()
List<Board> list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text);
if(type.equals("content")){
list = bRepository.findByContentIgnoreCaseContainingOrderByNoDesc(text);
}
else if(type.equals("writer")) {
list = bRepository.findByWriterIgnoreCaseContainingOrderByNoDesc(text);
}
else if(type.equals("title")){
list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text);
}
model.addAttribute("list", list);
return "/board2/selectlist";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java의 selectListGET을 위처럼 수정한다.
제목이 1이 포함된 게시글만 select한다.
작성자 이름에 ㅁ이 포함된 게시글만 select한다.
// 127.0.0.1:9090/ROOT/board2/selectlist.pknu
// 1. 전달값받기 ?page=1&type=writer&text=ㅓㅓㅗㅓㅗ
@GetMapping(value="/selectlist.pknu")
public String selectListGET(
Model model,
@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "type", defaultValue = "title") String type,
@RequestParam(name = "text", defaultValue = "") String text ) {
try {
if(page == 0) { // ? 가 없으면
return "redirect:/board2/selectlist.pknu?page=1&type=title&text=";
}
PageRequest pageRequest = PageRequest.of((page-1), 10);
List<Board> list = bRepository.findByTitleIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
long total = bRepository.countByTitleIgnoreCaseContainingOrderByNoDesc(text);
if(type.equals("content")) {
list = bRepository.findByContentIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
total = bRepository.countByContentIgnoreCaseContainingOrderByNoDesc(text);
}
else if(type.equals("writer")) {
list = bRepository.findByWriterIgnoreCaseContainingOrderByNoDesc(text, pageRequest);
total = bRepository.countByWriterIgnoreCaseContainingOrderByNoDesc(text);
}
model.addAttribute("list", list);
model.addAttribute("pages", (total-1)/10 + 1);
return "/board2/selectlist";
}
catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board2Controller.java의 selectListGET을 위처럼 수정, 추가하고
<body>
<h3>목록(board)</h3>
<a th:href="@{/board2/insertbatch.pknu}"><button>일괄추가</button></a>
<button th:onclick="formAction1(1)">일괄수정</button>
<button th:onclick="formAction1(2)">일괄삭제</button>
<hr />
<form th:action="@{/board2/selectlist.pknu}" method="get">
<input type="hidden" name="page" value="1" />
<select name="type">
<option value="title">제목</option>
<option value="content">내용</option>
<option value="writer">작성자</option>
</select>
<input type="text" name="text" placeholder="검색어" />
<input type="submit" value="검색" />
</form>
<form th:action="@{/board2/updatebatch.pknu}" method="post" id="form">
<table border="1">
<tr th:each="obj : ${list}">
<td><input type="checkbox" name="chk[]" th:value="${obj.no.longValue()}"/></td>
<td th:text="${obj.no.longValue()}"></td>
<td th:text="${obj.title}"></td>
<td th:text="${obj.writer}"></td>
<td th:text="${obj.hit.longValue()}"></td>
<td th:text="${obj.regdate}"></td>
</tr>
</table>
</form>
<th:block th:each="num : ${#numbers.sequence(1, pages)}">
<a th:href="@{/board2/selectlist.pknu( page=${num}, type=${param.type}, text=${param.text})}" th:text="${num}"></a>
</th:block>
<script th:inline="javascript" type="text/javascript">
function formAction1(code) {
const form = document.getElementById('form');
if(code === 1) {
form.action = /*[[@{/board2/updatebatch.pknu}]]*/'';
}
else if(code === 2) {
form.action = /*[[@{/board2/deletebatch.pknu}]]*/'';
}
form.submit();
}
</script>
</body>
selectlist.html을 위처럼 수정, 추가한다.
10개씩 페이지네이션이 된 모습을 볼 수 있다.
@Data
@Immutable // 뷰일경우 추가 => 조회만 가능한 엔티티
@Entity
@Table(name = "BOARD1_VIEW")
public class Board1View {
@Id
@Column( name = "NO")
private Long no = 0L;
@Column(name="TITLE")
private String title= null;
}
entity에 Board1View.java
@Data
@Immutable //뷰일경우 추가 => 조회만 가능한 엔티티...
@Entity
@Table(name = "PURCHASEVIEW")
public class PurchaseView {
@Id
@Column(name = "NO")
private BigDecimal no;
@Column(name = "CNT")
private BigDecimal cnt;
@Column(name="ITEMNO")
private BigDecimal itemNo;
@Column(name="ITEMPRICE")
private BigDecimal itemPrice;
@Column(name = "CUSTOMERID")
private String customerId = null;
@Column(name = "CUSTOMERNAME")
private String customerName = null;
@Column(name = "ITEMNAME")
private String itemName = null;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
@Column(name = "REGDATE")
private Date regdate;
}
PurchaseView.java를 생성한다.
public interface PurchaseViewRepository extends JpaRepository<PurchaseView, BigDecimal>{
}
PurchaseViewRepository.java도 생성한다.
@Slf4j
@Controller
@RequestMapping(value = "/purchaseview")
@RequiredArgsConstructor
public class PurchaseViewController {
final PurchaseViewRepository pvRepository;
// 127.0.0.1:9090/ROOT/purchaseview/selectlist.pknu
@GetMapping(value="/selectlist.pknu")
public String selectlistGET(Model model){
try{
List<PurchaseView> list = pvRepository.findAll();
model.addAttribute("list", list);
return "/purchase/selectlist";
}catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
}
PurchaseViewController.java
<body>
<h3>주문내역(purchaseview)</h3>
<hr />
<table border="1">
<thead>
<tr>
<th>주문번호</th>
<th>주문수량</th>
<th>물품번호</th>
<th>물품가격</th>
<th>고객아이디</th>
<th>고객이름</th>
<th>물품이름</th>
<th>주문일자</th>
</tr>
</thead>
<tbody>
<tr th:each="obj :${list}">
<td th:text="${obj.no.longValue()}"></td>
<td th:text="${obj.cnt.longValue()}"></td>
<td th:text="${obj.itemNo.longValue()}"></td>
<td th:text="${obj.itemPrice.longValue()}"></td>
<td th:text="${obj.customerId}"></td>
<td th:text="${obj.customerName}"></td>
<td th:text="${obj.itemName}"></td>
<td th:text="${obj.regdate}"></td>
</tr>
</tbody>
</table>
</body>
selectlist.html
5개의 파일을 생성하면
주문내역이 나오게 된다.
<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
<input type="text" placeholder="주문번호 입력" />
<input type="text" placeholder="물품이름 입력" />
<input type="submit" value="주문번호와 물품이름이 정확하게 일치하는 것만 조회" />
</form>
<hr />
<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
<input type="text" placeholder="주문번호 입력" />
<input type="text" placeholder="물품이름 입력" />
<input type="submit" value="주문번호와 물품이름 둘 중 하나 이상 일치하는 것만 조회" />
</form>
<hr />
<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
<input type="text" placeholder="주문번호를 ,로 구분해서 입력" />
<input type="submit" value="주문번호에 해당하는 항목만 조회" />
</form>
<hr />
<form th:action="@{/purchaseview/selectlist.pknu(num=1)}" method="get">
<input type="text" placeholder="물품이름을 ,로 구분해서 입력" />
<input type="submit" value="제목이 해당하는 항목만 조회" />
</form>
<hr />
해당하는 코드 짜기.
<form th:action="@{/board1view/selectlist.pknu}" method="get">
<input type="hidden" name="num" value="1" />
<input type="text" name="no" placeholder="글번호입력" />
<input type="text" name="title" placeholder="제목입력" />
<input type="submit" value="글번호와 제목이 정확하게 일치하는 것만 조회" />
</form>
<hr />
<form th:action="@{/board1view/selectlist.pknu}" method="get">
<input type="hidden" name="num" value="2" />
<input type="text" name="no" placeholder="글번호입력" />
<input type="text" name="title" placeholder="제목입력" />
<input type="submit" value="글번호 제목 둘 중 하나이상 일치하는 것만 조회" />
</form>
<hr />
<form th:action="@{/board1view/selectlist.pknu}" method="get">
<input type="hidden" name="num" value="3" />
<input type="text" name="no1" placeholder="글번호를 ,로 구분해서 입력" />
<input type="submit" value="글번호에 해당하는 항목만 조회" />
</form>
<hr />
<form th:action="@{/board1view/selectlist.pknu}" method="get">
<input type="hidden" name="num" value="4" />
<input type="text" name="title" placeholder="제목을 ,로 구분해서 입력" />
<input type="submit" value="제목이 해당하는 항목만 조회" />
</form>
<hr />
각각 name을 지정해준다.
@Repository
public interface Board1ViewRepository extends JpaRepository<Board1View, Long>{
// 0 or 없으면
List<Board1View> findAllByOrderByNoDesc();
// 1번
List<Board1View> findByNoAndTitleOrderByNoDesc (long no, String title);
// 2번
List<Board1View> findByNoOrTitleOrderByNoDesc (long no, String title);
// 3번
List<Board1View> findByNoIn(long[] no);
// 4번
List<Board1View> findByTitleIn(String[] title);
}
jpa문을 작성한다.
// 127.0.0.1:9090/ROOT/board1view/selectlist.pknu
@GetMapping(value="/selectlist.pknu")
public String selectlistGET( Model model,
@RequestParam(name="num", defaultValue = "0") int num,
@RequestParam(name="title", defaultValue = "") String title,
@RequestParam(name="no", defaultValue = "0") long no,
@RequestParam(name="no1", defaultValue = "")String no1 // split을 사용하기 위해 String으로 정의
){
try{
List<Board1View> list = b1vRepository.findAll();
if(num == 1){
list = b1vRepository.findByNoAndTitleOrderByNoDesc(no, title);
}
else if(num == 2){
list = b1vRepository.findByNoOrTitleOrderByNoDesc(no, title);
}
else if(num == 3){
String[] arr = no1.split(","); // split을 사용하여 String[] arr 배열에 저장
long[] arrl = new long[arr.length]; // 깡통 배열을 생성하여 long[] arrl에 넣을 것이다.
for(int i =0; i<arr.length; i++){ // arr의 길이만큼 반복
arrl[i] = Long.parseLong(arr[i]); // arrl에 넣음
}
list = b1vRepository.findByNoIn(arrl);
}
else if(num == 4){
String[] t = title.split(",");
list = b1vRepository.findByTitleIn(t);
}
model.addAttribute("list", list);
return "/board1view/selectlist";
}catch(Exception e){
e.printStackTrace();
return "redirect:/home.do";
}
}
Board1ViewController에 작성.
1번 문제
2번 문제
3번 문제
4번 문제