-
Spring Boot JPA를 통해 Tibero6와 연동하기Tibero DB (Tmax AI Bigdata Academy) 2023. 10. 28. 11:39
벌써 교내에서 진행하는 TABA 수업의 운체, AI, DB, Tibero 시험들이 모두 끝났다..
이제 팀별 프로젝트만을 남겨두고 있는데, 백엔드를 공부하고 있기때문에 Spring Boot와
이번 프로젝트에서 DB를 평소에 사용하던 MySQL이 아닌 Tibero6를 사용해보고 싶어 미리 기록해두려고 한다.
(이러고 스프링이랑 티베로 안쓰면 ㅠㅠ)📖 참고
Tibero6를 윈도우나 리눅스 환경에서 설치했다고 가정하고
연동했던 과정을 기록했습니다.
📒Window 환경에서 Tibero6 설치
https://codecollector.tistory.com/1613
📒Linux(Ubuntu) 환경에서 Tibero6 설치
https://kjungw1025.tistory.com/4
📖 tibero6-jdbc.jar file 확인
우선 JDBC(Java Database Connectivity)란 Java 기반 애플리케이션의 데이터를 데이터베이스에 저장 및 업데이트 또는 java에서 사용할 수 있도록 하는 API이다.
Tibero에서는 Tibero DB와 연결을 도와주기 위해 JDBC API를 제공하는데, 이를 tbJDBC(Tibero의 Java Database Connectivity)라고 부른다.
Tibero6를 설치하면서 제공되는 드라이버 파일은 아래 경로에 위치한다.
Window
C:\TmaxData\tibero6\client\lib\jar
Linux
/tibero6/client/lib/jar
위 사진처럼 경로에 들어가면 tibero6-jdbc.jar과 tibero6-jdbc-14.jar파일이 존재한다.
Tibero 6 Online Manual을 확인해보면, JDK 버전이 1.4인 경우에는 tibero6-jdbc-14.jar 파일을 사용하고
JDK 6 이상에서 드라이버 파일은 tibero6-jdbc.jar 파일을 사용하면 된다고 설명하고 있다.
나의 경우 JDK 17이 설치되어있기 때문에 tibero6-jdbc.jar 파일을 사용할 예정이다.
# 터미널에서 jdk 버전 확인 java --version
📖 Spring Boot JPA
📒 프로젝트 생성
Spring Initializr를 사용해 프로젝트를 생성했다.
📒tibero6-jdbc.jar 추가
위에서 확인한 tibero6-jdbc.jar 파일을, 생성한 스프링부트 폴더안의 src 폴더와 같은 level에
별도의 libs 폴더를 만들어 libs 폴더안에 넣어준다.
📒build.gradle 설정
build.gradle안의 dependencies에 추가한 jar의 경로를 넣어 build해준다.
plugins { id 'java' id 'org.springframework.boot' version '2.7.17' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'taba' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation files('libs/tibero6-jdbc.jar') compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
📒application.yml 설정
spring: datasource: driver-class-name: com.tmax.tibero.jdbc.TbDriver url: jdbc:tibero:thin:@127.0.0.1:8629:tibero username: sys password: tibero jpa: # 문법 정의 : tibero는 oracle 문법을 사용하므로 database-platform: org.hibernate.dialect.Oracle10gDialect hibernate: ddl-auto: update properties: hibernate: format_sql: true show_sql: true highlight_sql: true default_batch_fetch_size: 200
📒Entity 작성
Tibero6 연동을 확인하기 위해 아래 사진처럼 패키지들을 만들어 수행하고자 한다.
domain 패키지 안에 Member.java 생성
package taba.tibero6jpa.user.domain; import lombok.*; import javax.persistence.*; import javax.validation.constraints.NotNull; @Entity @Table(name="member") @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Member { @Id @GeneratedValue @Column(name = "member_id") private Long id; @NotNull @Column(length = 20) private String name; @NotNull private String phone; @Builder private Member(@NotNull String name, @NotNull String phone) { this.name = name; this.phone = phone; } }
📒DTO 작성
RequestMemberDto.java
package taba.tibero6jpa.user.domain; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import javax.validation.constraints.NotBlank; @Getter @Setter @RequiredArgsConstructor public class RequestMemberDto { @NotBlank private String name; @NotBlank private String phone; }
📒Repository 작성
package taba.tibero6jpa.user.repository; import org.springframework.stereotype.Repository; import taba.tibero6jpa.user.domain.Member; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.List; @Repository public class MemberRepository { @PersistenceContext // JPA가 제공하는 표준 어노테이션 private EntityManager em; // Spring이 Entity manager를 만들어서 주입하게 해줌 public void save(Member member) { em.persist(member); } public List<Member> findAll() { List<Member> result = em.createQuery("select m from Member m", Member.class) .getResultList(); return result; } public List<Member> findByName(String name) { return em.createQuery("select m from Member m where m.name = :name", Member.class) .setParameter("name", name) .getResultList(); } }
📒Service 작성
package taba.tibero6jpa.user.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import taba.tibero6jpa.user.domain.Member; import taba.tibero6jpa.user.domain.RequestMemberDto; import taba.tibero6jpa.user.repository.MemberRepository; import java.util.List; @Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; @Transactional public Long join(RequestMemberDto dto) { validateDuplicateMember(dto); Member member = Member.builder() .name(dto.getName()) .phone(dto.getPhone()) .build(); memberRepository.save(member); return member.getId(); } private void validateDuplicateMember(RequestMemberDto dto) { List<Member> findMembers = memberRepository.findByName(dto.getName()); if (!findMembers.isEmpty()) { throw new IllegalStateException("이미 존재하는 회원입니다."); } } @Transactional(readOnly = true) public List<Member> findMembers() { return memberRepository.findAll(); } @Transactional(readOnly = true) public List<Member> findByName(String name) { return memberRepository.findByName(name); } }
📒 실행 및 테이블 생성 확인
application을 실행하면 터미널상에 아래와 같이 테이블이 생성된 것을 log로 확인할 수 있다.
그렇다면 Tibero6 DB에도 테이블이 잘 생성되었을까? 확인해보자!
다음과 같이 성공적으로 테이블이 생성된 것을 확인할 수 있다.
📖 Thymeleaf 템플릿 엔진을 통해 로컬 환경에서 웹 띄워보기
사실 위에서 끝내도 되긴하지만,
간단하게 Thymeleaf를 통해 뷰 템플릿을 작성하고
컨트롤러로 전달하는 데이터를 이용하여 동적으로 웹 화면을 보여주는 것까지 하고 마무리하려고 한다.
📒controller
package taba.tibero6jpa.user.controller; import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import taba.tibero6jpa.user.domain.Member; import taba.tibero6jpa.user.domain.RequestMemberDto; import taba.tibero6jpa.user.service.MemberService; import java.util.List; @Controller @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @GetMapping("/members/new") public String createForm(Model model) { model.addAttribute("memberForm", new RequestMemberDto()); return "members/createMemberForm"; } @PostMapping("/members/new") public String create(@Valid RequestMemberDto dto, BindingResult result) { if (result.hasErrors()) { return "members/createMemberForm"; } memberService.join(dto); return "redirect:/"; } @GetMapping("/members") public String list(Model model) { List<Member> members = memberService.findMembers(); model.addAttribute("members", members); return "members/memberList"; } }
📒HTML 작성
resources > static > templates에 아래 html들을 작성하자
createMember.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymleaf.org"> <body> <div> <form action="/members/new" method="post"> <div> <label for="name">이름</label> <input type="text" id="name" name="name" placeholder="이름을 입력하세요."> <label for="phone">전화번호</label> <input type="text" id="phone" name="phone" placeholder="전화번호를 입력하세요."> </div> </form> </div> </body> </html>
memberList.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <body> <div> <div> <table> <thead> <tr> <th>#</th> <th>이름</th> <th>전화번호</th> </tr> </thead> <tbody> <tr th:each="member : ${members}"> <td th:text="${member.id}"></td> <td th:text="${member.name}"></td> <td th:text="${member.phone}"></td> </tr> </tbody> </table> </div> </div> </body> </html>
📒로컬 환경에서 확인하기
처음 /members에 들어가면 현재 Member 테이블에 값들이 비어있기 때문에 아래와 같이 나온다.
/members/new에 들어가서 값을 insert해주자
입력 버튼을 누르면 /members로 리다이렉트 했기 때문에 아래와 같이 값이 잘 적용된 것을 확인할 수 있다.
터미널에서도 아래와 같이 query문이 잘 동작하는 것을 확인할 수 있다.
사용자가 input tag에 값을 넣고 입력 버튼을 누르면, Hibernate의 시퀀스 전략으로 nextval이 호출되면서
name, phone값과 함께 Insert되고,
/members 페이지로 가면서 Member 테이블에 존재하는 값들 전부를 select하는 과정이다.
Tibero6 DB에도 값이 문제 없이 Insert된 것을 확인할 수 있다.
'Tibero DB (Tmax AI Bigdata Academy)' 카테고리의 다른 글
Tmax AI Bigdata Academy 4기를 마치며 (0) 2023.12.19 Spring Boot JPA와 Tibero6 연동 간 발생했던 에러들 정리 (0) 2023.11.11 tbstudio 실행 및 기능 살펴보기 (0) 2023.10.22 pyodbc를 이용하여 Tibero DB에 대한 query문 작성하기 (0) 2023.10.17 Ubuntu 환경에서 ODBC를 통해 Tibero와 Python 연동하기 (2) 2023.10.16