
Spring Batch 를 개발하면서 JPA 를 한번 써보고 싶어서 JPA 로 구현해 보았다.
📢 JPA 는 인터페이스로서 자바 표준 명세서 이다. JPA 를 사용하기 위해서는 구현체가 필요한데,
대표적으로 Hibernate, Eclipse Link 등이 있다.
하지만 Spring 에서는 JPA 를 사용할 때 이 구현체들을 직접 다루지 않고, 더 쉽게 사용하고자 추상화 시킨
Spring Data JPA 라는 모듈을 이용하여 JPA 기술을 다룬다.
1. pom.xml
<!-- JPA 설정 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.11.0</version>
</dependency>
- spring-boot-starter-data-jpa : 스프링 부트용 Spring Data Jpa 추상화 라이브러리.
- H2 : 인메모리 관계형 데이터베이스, 메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화됨
2. JPA 인터페이스 구현
2-1. Entity 클래스 생성
import javax.persistence.*;
import java.io.Serializable;
@Entity
//@Data
@Table(name = [테이블명])
public class SAPL231Entity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "SUBJT_CD", nullable = false)
private String subjtCd;
@Column(name = "SUBJT_NM")
private String subjtNm;
@Column(name = "SMT_CD")
private String smtCd;
@Column(name = "STUNO" , nullable = false)
private String stuno;
@Column(name = "SYY")
private String syy;
@Column(name = "ATNLC_DTA_DEL_DISP_CD")
private String atnlcDtaDelDispCd;
}
자세한 설명은 더보기 확인 바랍니다.
@Entity란 ? DB에서 영속적으로 저장된 데이터를 자바 객체로 매핑하여 '인스턴스의 형태' 로 존재하는 데이터.
@Entity 가 붙은 클래스는 JPA 가 관리한다.
※ 주의사항 : 기본생성자는 필수, final 클랙스, enum, interface, inner class 에는 사용할 수 없다.
저장할 필드에 final 사용불가.
@Entity : Entity 클래스임을 명시
@Table(name = [테이블명]) : 매핑할 테이블 명을 지정.
@Id : 기본키. 모든 Entity 는 @Id 설정이 필요 (기본키가 복합키 인 경우, @Embedded 사용)
@Column : Entity 의 모든 필드는 데이터베이스의 컬럼과 매핑되어 따로 명시하지 않아도 된다.
하지만, 컬럼명이 다르거나 default 값이 다른 경우에 사용
++ 연관관계 매핑 : @ManyToOne, @JoinColumn
Entity 로 설정한 대로, 테이블이 생성 된다~
2-2. Repository 클래스 생성
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import [패키지].db.entity.SAPL231Entity;
import java.util.List;
import java.util.Map;
@Repository
public interface SubjectRepository extends JpaRepository<SAPL231Entity, String>, JpaSpecificationExecutor<SAPL231Entity>{
@Query(value =
" SELECT SUBJT_CD\n"+
" , STUNO\n"+
" FROM [SCHEMA].[TABLE명]\n"+
" WHERE 1 = 1\n"+
" AND SYY = :syy\n"+
" AND SMT_CD = '10'\n"+
" AND ATNLC_DTA_DEL_DISP_CD = '10'\n"+
" AND SUBJT_CD = :subjtCd\n",
nativeQuery = true)
List<Map<String, Object>> findMemberListSubjtCd(@Param("syy") String syy, @Param("subjtCd") String subjtCd);
}
자세한 설명은 더보기 확인 바랍니다.
iBatis나 MyBatis 등에서 Dao 라고 불리는 DB Layer 접근자. (JPA 에서는 Repository라고 부르며 인터페이스로 생성함)
단순히 인터페이스를 생성 후, JpaRepository<Entity 클래스, PK 타입> 을 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.
📊 JpaRepository 에 대한 설명
JpaRepositoey 는 PagingAndSortingRepository, QueryByExampleExecutor 인터페이스를 상속받음.
PagingAndSortingRepository 는 CrudRepository 인터페이스를 상속 받고 있어서 기본적인 CRUD 메소드를 제공한다.
-> save(), findById(), existById(), count(), deleteById(), delete(), deleteAll()
QueryByExampleExecutor 에서는 findOne(), findAll(), count(), exists() 를 제공한다.
2-3. 테스트 코드 작성
@Test
void Jpa_test() throws Exception{
ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
SubjectRepository rep = context.getBean(SubjectRepository.class);
List<Map<String, Object>> result = rep.findMemberListSubjtCd("2023", "U000437");
System.out.println(result.get(0));
}
2-4. application.proptertise
spring.jpa.database=oracle
spring.jap.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.hibernate.ddl-auto=validate
디비가 tibero 인 경우에는 tibero와 유사한 데이터베이스 타입으로 설정하면 된다.
2-1 ~ 2-4 까지만 설정하면
15:12:45.142 WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: -8033, SQLState: 42S02
15:12:45.142 ERROR o.h.e.jdbc.spi.SqlExceptionHelper - JDBC-8033:Specified schema object was not found.
at line 3, column 8 of null:
FROM [SCHEMA].[TABLE명]
^
해당 오류가 계속해서 발생할 것이다..
만약에 테이블에 별다른 스키마가 없다면 상관없지만, 본인은 스키마가 별도로 필요하기 때문에 스키마를 붙으면 오류가 나서 만약에 스키마를 빼고 하면, 데이터가 존재하는데 데이터가 조회되지 않는 오류가 있다.
그래서 스키마에 대해 검색해보면, @Entity 를 설정할때, catalog 또는 schema 를 붙이면 된다고 하는데도 오류는 해결되지 않았다 ㅠㅠ
해결책은 아래 @EnableJpaRepositories 와 em.setPackagesToScan 을 통해 해결하였다!!
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableJpaRepositories(
basePackages = "[JPA Repository 패키지 명]", // jpa Repository 위치
entityManagerFactoryRef = "masterEntityManager",
transactionManagerRef = "masterTransactionManager"
)
public class JpaDataSourceConfiguration {
@Autowired
@Qualifier("tiberoDataSource")
private DataSource tiberoDataSource;
@Bean
public LocalContainerEntityManagerFactoryBean masterEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(tiberoDataSource);
//Entity 패키지 경로
em.setPackagesToScan(new String[] { "[JPA Entity 패키지 명]" });
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
//Hibernate 설정
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto","validate");
properties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
properties.put("hibernate.show_sql","true");
properties.put("hibernate.format_sql","true");
em.setJpaPropertyMap(properties);
return em;
}
@Bean
public PlatformTransactionManager masterTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(masterEntityManager().getObject());
return transactionManager;
}
Hibernate 에 대한 자세한 설명 및 참고블로그에 대한 기록은 더보기 참고부탁드립니다.
📌 Jpa 와 Hibernate 란 ? 📌
Jpa 는 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스 이다.
JPA는 특정기능을 하는 라이브러리가 아닌 인터페이스이다. (어떻게 사용해야하는지 정의하는 한 방법)
단순명세 이기 때문에 구현이 없다. 그러므로 JPA의 구현체 역할을 하는 것이 Hibernate 이다!

만약에
//Hibernate 설정
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto","validate");
properties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
properties.put("hibernate.show_sql","true");
properties.put("hibernate.format_sql","true");
em.setJpaPropertyMap(properties);
hibernate 설정하는 부분을 해주지 않으면 아래와 같이 Dialect(방언) 이 정의 되지 않았다는 오류가 발생한다.
12:04:36.898 INFO com.zaxxer.hikari.pool.PoolBase - HikariPool-1 - Driver does not support get/set network timeout for connections. (com.tmax.tibero.jdbc.driver.TbConnection.getNetworkTimeout()I)
12:04:36.930 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
12:04:36.997 WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata
org.hibernate.HibernateException: Unable to determine Dialect to use [name=Tibero, majorVersion=6]; user must register resolver or explicitly set 'hibernate.dialect'
아래 블로그를 참고하여 정리하였다.
https://annajin.tistory.com/192
[JPA] JPA, Hibernate, Spring Data JPA의 차이점
들어가며 짧은 시간 내에 JPA를 프로젝트에 적용하기 위해서 JPA를 제대로 공부할 시간 없이 바로 코드에 적용하느라고 수많은 에러를 만나고 해결해보았다. 하지만 코드를 작성하면서 EntityManager
annajin.tistory.com
https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/
JPA, Hibernate, 그리고 Spring Data JPA의 차이점
개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레
suhwan.dev
아래 블로그를 참고하였다.
https://velog.io/@lehdqlsl/SpringBoot-JPA-Multiple-Databases-%EC%84%A4%EC%A0%95
SpringBoot JPA Multiple Databases 설정
다중 DB는 Spring boot 처럼 Auto Configuration되지 않음설정파일(application.yml 또는 application.properties) 값을 읽어와서 연동 할 DB 수 만큼 Datasource를 수동 설정해야함설정파일 대신 코드로 직접 설
velog.io
https://willbfine.tistory.com/559
<Spring Batch> 3. 배치 테이블 Embedded DB(H2)로 따로 관리하기
출처 : http://www.yes24.com/Product/Goods/99422216 스프링 배치 완벽 가이드 2/e - YES24 스프링 배치의 `Hello, World!`부터 최근 플랫폼의 발전에 따른 클라우드 네이티브 기술을 활용한 배치까지 폭넓은 스프링
willbfine.tistory.com
https://m.blog.naver.com/hj_kim97/222780110215
[Spring JPA]JpaRepository 기본 사용법
JpaRepository 기본 사용법 - Spring Data JPA - Spring Data JPA 사용하기 - JPA를 사용한...
blog.naver.com
'Java > Spring Batch' 카테고리의 다른 글
| Spring Batch + 구현 (0) | 2023.07.11 |
|---|---|
| Spring Batch + Tibero 연동 (1) | 2023.06.22 |