spring 타임리프와 JPA 사용해서 데이터 입력 페이지 만들기

호연지기·2023년 6월 1일
0

타임리프와 JPA를 활용해서 데이터를 입력하고 검색하는 페이지를 만든다.

Point

  • 데이터입력 링크를 누르면 데이터 입력 페이지로 넘어간다.
  • 데이터 목록 섹션에서 데이터 목록을 출력한다.
  • 문자열을 검색하면 해당 컬럼을 보여준다.

🔰 JPA란?

자바 어플리케이션에서 관계형 데이터베이스를 사용하는
방식을 정의한 인터페이스 관련 API.

관계형 데이터베이스(RDB)

테이블(엔티티)과 테이블 간의 관계로
데이터를 저장하는 방식의 데이터베이스
    - MySQL, 오라클, 마리아DB 등.

Hibernate : JPA의 구현체 (JPA는 인터페이스, Hibernate는 구현 클래스)

Spring Data JPA : JPA와 Hibernate를 사용하기 쉽게 만든 Spring 라이브러리.

Entity 클래스(DTO)를 구현하면 해당 클래스에서 지정한 테이블 이름 및 컬럼 이름으로
DB 테이블을 자동으로 생성하며, DB CRUD에 대한 메소드도 제공.
메소드 이름으로 SQL 쿼리문을 생성하는 방식을 사용한다.

🔰 application.properties 세팅

JPA 초기화 전략 설정(a.k.a JPA 설정)

spring.jpa.generate-ddl : true로 설정하면 해당 데이터를 근거로 서버 시작 시에 DDL문을 생성하여 DB에 적용.
DDL 생성 시 데이터베이스 고유의 기능을 사용하는지에 대한 유무 체크.
false로 설정.

spring.jpa.hibernate.ddl-auto : 'create table' 관련 설정.

  • none : 아무런 작업도 하지 않음.(DB에 테이블을 따로 생성)
  • create : 서버가 시작할 때 기본 테이블을 DROP(제거)하고 새 DDL을 실행(테이블 재생성)
  • create-drop : 서버가 시작할 때 DROP 및 CREATE하고, 서버가 종료될 때 DROP 실행.
  • update : 기존 테이블에 해당하는 Entity 클래스가 변경되면 기존 테이블을 DROP하고,새 클래스에 맞게 테이블 생성. 변경된 내용이 없으면 테이블 유지.
  • validate : Entity와 테이블이 잘 맵핑되어 있는지 확인하여, 맞지 않을 경우 프로그램을 종료시킨다.

spring.jpa.database-platform : 각 DBMS에 맞게 SQL을 생성하도록 도와주는 dialect(방언) 객체를 지정한다.

tyhmeleaf 설정

# DevTools setting
spring.devtools.livereload.enabled=true
spring.devtools.restart.enabled=true
spring.thymeleaf.cache=false

# static resource
spring.web.resources.static-locations=classpath:static/

DB 설정

# datasource setting
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/berrydb?serverTimezone=Asia/Seoul
#DB유저 id, 비밀번호
spring.datasource.username=buser
spring.datasource.password=12341234

JPA 설정

# JPA setting
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=false

spring.jpa.hibernate.ddl-auto=update

# JPA log setting
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
logging.level.org.hibernate.type.descriptor.sql=trace

🔰 entity, repository 생성

Entity class

DB 테이블과 연계하기 위한 클래스.
DTO의 역할도 함께 처리할 수 있음.(따로 작성하는 경우가 일반적임)

Repository 인터페이스

DAO 역할을 하는 인터페이스.
이 인터페이스 내부에 다양한 작업을 위한 메소드를 작명 규칙에 맞게 작성한다.

💻 JpaData 소스 (Entity class)

@Entity //entity임을 선언하는 어노테이션(DB DDL 생성 시 활요)
@Table(name="jpatbl") //DB 테이블의 이름을 지정하는 어노테이션. 생략 시 클래스 이름으로 테이블 생성.
@Data //Lombok 어노테이션
public class JpaData {
    @Id //필드를 테이블의 기본키로 설정하는 어노테이션
    @GeneratedValue(strategy = GenerationType.IDENTITY) //자동으로 생성되는 키값에 대한 설정
    private Long code;

    @Column(name = "str_data", nullable = false, length = 50) //nullable=false : null을 허용하지 않는다.
    private String strdata;

    @Column(name = "int_data")
    private int intdata;

    @Column(name = "reg_date")
    @CreationTimestamp //작성일 기준으로 db에 저장한다.
    private Timestamp regdate;
}

jpatbl 테이블을 만들어주는 entity class

💻 JpaDataRepository 소스

public interface JpaDataRepository extends JpaRepository<JpaData, Long> {
    //DB CRUD(insert, update, delete, select 용 인터페이스)
    //기본으로 전체 내용 삽입, 전체 내용 수정, 행 삭제
    //전체 내용 검색 및 키 검색용 메소드를 제공.
    List<JpaData> findByStrdata(String strdata);
    //SELECT * FROM jpatbl WHERE str_data = 'abcd'
}

인터페이스로 작성하며 메소드를 이용해서 데이터를 조작한다.

🔰 데이터 입력

💻 home.html 소스

<html lang="ko" xmlns:th="http://www.thymeleaf.org">
  
<h1>첫 페이지</h1>
<a th:href="@{writeForm}">[데이터입력]</a>

home페이지에서는 데이터 입력 클릭창만 보여주고 [데이터입력] 버튼 클릭스 writeForm 페이지로 이동한다.

💻 writeForm.html 소스

<html lang="ko" xmlns:th="http://www.thymeleaf.org">
  
<h1>데이터 입력</h1>
<form th:action="@{dataProc}" method="post">
  <input type="text" name="strdata"><br>
  <input type="number" name="intdata"><br>
  <input type="submit" value="Send">
</form>

writeForm 페이지에서는 데이터 입력 창을 보여주고 해당 데이터는 dataProc를 통해서 처리하도록 th:action 태그를 걸어준다.

💻 HomeController 소스

//writeForm.html로 보내주는 컨트롤러 동작
@GetMapping("writeForm")
public String writeForm(){
    log.info("writeForm()");
    return "writeForm";
}

//서비스의 insertData 작업을 받아서 view로 결과를 내보낸다.
@PostMapping("dataProc")
public String dataProc(JpaData data){
    log.info("dataProc()");
    String view = jServ.insertData(data);

    return view;
}

💻 JpaDataService 소스

@Autowired
private JpaDataRepository jRepo;

public String insertData(JpaData data){
    log.info("insertData()");
    String view = null;

    try{
        jRepo.save(data);//insert/update
        view = "redirect:/";
    } catch (Exception e){
        e.printStackTrace();
        view = "redirect:writeForm";
    }
    return view;
}

JpaDatadata로 받아서 리포지토리로 넘겨 사용자가 입력한 데이터를 DB에 저장한다.
저장에 성공하면 redirect를 이용해서 메인 페이지로 이동하고, 실패 시에는 writeForm 화면을 유지한다.

input 입력창에 데이터를 입력 후 Send로 데이터를 전송하면

첫페이지로 이동하면서 데이터 목록에 방금 입력한 데이터와 함께 데이터 목록이 출력된다.

🔰 데이터 목록

💻 home.html 소스

<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<!-- 데이터 목록 -->
<h2>데이터 목록</h2>
<table border="1">
    <thead>
    <tr>
        <th width="50">번호</th>
        <th width="200">문자열</th>
        <th width="100">숫자</th>
        <th width="200">날짜와 시간</th>
    </tr>
    </thead>
    <tbody>
    <th:block th:if="${#lists.isEmpty(jList)}">
        <tr><td colspan="4">데이터가 없습니다.</td></tr>
    </th:block>
    <th:block th:unless="${#lists.isEmpty(jList)}">
        <th:block th:each="item:${jList}">
            <tr>
                <td th:text="${item.code}"></td>
                <td th:text="${item.strdata}"></td>
                <td th:text="${item.intdata}"></td>
                <td th:text="${#dates.format(item.regdate,'yyyy-MM-dd HH:mm:ss')}"></td>
            </tr>
        </th:block>
    </th:block>
    </tbody>
</table>

DB에 저장된 데이터 목록을 가져오는 html소스
타임리프로 jList를 불러온다.

💻 HomeController 소스

@GetMapping("/")
public ModelAndView home(){
    log.info("home()");
    mv = jServ.getList();
    return mv;
}

서비스에서 getList 메소드 작업해서 ModelAndView로 가져오는 역할

💻 JpaDataService 소스

@Autowired
private JpaDataRepository jRepo;

private ModelAndView mv;

public ModelAndView getList(){
    log.info("getList()");
    mv = new ModelAndView();
    mv.setViewName("home");
    //목록 추가 작업
    List<JpaData> jList = jRepo.findAll();
    //findAll() -> SELECT * FROM table
    mv.addObject("jList", jList);

    return mv;
}

데이터를 home.html로 반환하기 위해서 ModelAndView로 getList 메소드를 생성하고 리포지토리를 사용해서 JpaData 데이터를 jList로 반환한다.

만약 리스트가 없다면 데이터가 없습니다. 문자열을 내보낸다.

🔰 데이터 검색

검색할 문자열을 input 창에 넣고 검색을 누르면

데이터 목록에서 검색한 결과값만 나타나는 것을 확인할 수 있다.

💻 home.html 소스

<html lang="ko" xmlns:th="http://www.thymeleaf.org">
  
<form th:action="@{search}" method="get">
    <input type="text" name="keyword" placeholder="검색할 문자열을 입력하세요.">
    <input type="submit" value="검색">
</form>

💻 HomeController 소스

@GetMapping("search")
public ModelAndView search(String keyword){
    log.info("search()");
    mv = jServ.getData(keyword);

    return mv;
}

컨트롤러는 search action태그를 받고 getData 서비스 처리로 넘겨주는 역할을 한다.

💻 JpaDataService 소스

public ModelAndView getData(String keyword) {
    log.info("getData()");
    mv = new ModelAndView();
    mv.setViewName("home");
    List<JpaData> jList = jRepo.findByStrdata(keyword);
    mv.addObject("jList", jList);
    return mv;
}

검색 문자열을 keyword로 보내서 해당 문자열의 데이터만 보여지도록 한다.

📅 DATE

2023.06.01 작성

profile
사람의 마음에 차 있는 너르고 크고 올바른 기운

0개의 댓글