JPA 환경설정 및 사용법(+mariaDB)

이수빈·2023년 8월 7일
0

Spring

목록 보기
3/4
  • JPA를 mariadb와 연동하는 과정과 사용법들을 정리해보고자 한다.

JPA란?(Java Persistence API)

  • Java에서 데이터베이스를 다루기 위한 표준 ORM 기술임 => RBD와 자바 객체간의 매핑을 지원해서 데이터베이스에 저장된 정보를 객체지향적으로 다룰 수 있게 도와줌

  • JPA를 구현한 프레임워크로는 Hibernate, EclipseLink, OpenJPA 존재함 => 여기서 Hibernate를 사용했음.

JDBC란?(Java Database Connectivity)

  • JDBC는 데이터베이스와 자바 애플리케이션 사이에서 중간 계층 역할을 수행하여 데이터베이스 관련 작업을 추상화하고 표준화함 => DB에 상관없이 표준화된 코드로 데이터베이스에 접근가능함.

  • JDBC를 사용하면 데이터베이스와의 접속, SQL 쿼리 실행, 결과 처리 등의 작업을 자바 코드로 처리할 수 있음.

  • JDBC는 인터페이스고, 구현한 것은 각 데이터베이스에 맞는 드라이버들임.

  • JPA는 데이터베이스와 객체를 매핑하는 기술일 뿐, 내부적으로는 데이터베이스와의 통신을 위해 JDBC를 사용한다.

  • 또한 JPA도 JDBC와 마찬가지로 인터페이스이기 때문에 구현체가 필요하고, 그 구현체 중 하나가 Hibernate(가장 널리 사용됨)인 것.

JPA Maria DB와 연동하기

build.gradle 설정

  • maria db jdbc와 jpa starter를 추가한다.
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
}

DB설정

  • application.properites에 mariadb 연결정보를 작성한다.
spring.datasource.url=jdbc:mariadb://localhost:[설정포트]/[db이름]
spring.datasource.username=[설정유저네임]
spring.datasource.password=[비번]
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
  • 여기서 spring.jpa.hibernate.ddl-auto=update 옵션은 ‘JPA 엔티티 설계’와 ‘실제 테이블 상태’를 비교하여, 차이점이 있다면 그것을 테이블에 반영하는 옵션이다.

  • 칼럼삭제의 경우 테이블의 칼럼이 엔티티에 존재하지 않아도 삭제되지 않음.

ddl option 종류
create: 기존테이블 삭제 후 다시 생성 (DROP + CREATE)
create-drop: create와 같으나 종료시점에 테이블 DROP
update: 변경분만 반영(운영DB에서는 사용하면 안됨)
validate: 엔티티와 테이블이 정상 매핑되었는지만 확인
none: 사용하지 않음(사실상 없는 값이지만 관례상 none이라고 한다.)

JPA Entity, Repository 생성

Entity 설정

  • Entity란 DB테이블에 대응하는 클래스이다.

  • @SqlResultMapping 어노테이션은 => createNativeQuery에서 sql쿼리문을 통해 Entity가 아닌 DTO로 직접 매핑하기 위해서 사용하는 어노테이션이다.

  • @Column 어노테이션으로 길이와 이름을 지정 할 수 있다.

  • 기본적으로 Entity는 camelCase로 작성하고, 이것은 DB에서 snake_case로 매핑된다.(이렇게 작성하는 것이 기본 규칙)

  • 다른 방식으로 매핑을 해주려면 @Column 어노테이션의 name 값을 직접 지정해줘야 한다.

import javax.persistence.*;
import java.math.BigInteger;
import java.sql.Date;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "exampleEntitiy")
@SqlResultSetMapping(
        name = "contractDTOMapping",
        classes = @ConstructorResult(
                targetClass = ContractDTO.class,
                columns = {
                        @ColumnResult(name = "contractEndDate", type = String.class),
                        @ColumnResult(name = "contractPlace", type = String.class),
                        @ColumnResult(name = "autoSeller", type = String.class),
                        @ColumnResult(name = "carNum", type = String.class),
                        @ColumnResult(name = "rentFullMonth", type = Integer.class),
                        @ColumnResult(name = "rentStartDate", type = String.class),
                        @ColumnResult(name = "rentEndDate", type = String.class),
                        @ColumnResult(name = "rentManageNum", type = String.class),
                        @ColumnResult(name = "cusName", type = String.class),
                        @ColumnResult(name = "repairCode", type = String.class),
                        @ColumnResult(name = "cusCode", type = String.class),
                        @ColumnResult(name = "insuAgeCode", type = String.class),
                        @ColumnResult(name = "insuGuarantee", type = String.class),
                        @ColumnResult(name = "insuSelfMoneyCode", type = String.class),
                        @ColumnResult(name = "rentSpecialCode", type = String.class),
                        @ColumnResult(name = "carInfo", type = String.class),
                        @ColumnResult(name = "depositPrice", type = Integer.class),
                        @ColumnResult(name = "totalPrice", type = Integer.class),
                        @ColumnResult(name= "monthlyPayPrice", type= Integer.class)

                }
        )
)
public class exampleEntitiy {

    @Id
    @Column(name="cntt_no")
    private String cnttNo;
    @Column(name="rq_no",length = 15)
    private String rqNo;
    @Column(length = 12)
    private String cnttRqsNo;
    @Column(length = 9)
    private String lndCntdNo;
    @Column(length = 15)
    private String saleCnttNo;
    @Column(length = 2)
    private String cnttScnCd;
    @Column(length = 2)
    private String cnttStCd;
    @Column(length = 2)
    ...
    ...
    

Repository 생성

  • 기본키 제외 다른키를 통해 DB에서 조회하려면 메소드를 Repository에 작성해줘야 한다.

  • 이렇게 만든 Repo를 Service에서 가져와 코드를 작성한다.

package subin.OJT.Repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.math.BigInteger;
import java.util.List;


@Repository
public interface db_Repository extends JpaRepository<db, String> {
//     추가적인 메서드 선언이 필요한 경우 작성
//     <T, ID> 형식, ID의 type을 맞춰줘야함.

    List<KRCA_CNTT_I> findAllByCsmrSn(BigInteger CSMR_SN);

//    @Query(value="", nativeQuery = true)
//    List<ContractDTO> findContractInfo();


}
  • Service 예시

  • 복잡한 쿼리문을 작성할 때는 createNativeQuery를 이용한다.


@Service
public class ContractService {
    @PersistenceContext
    private EntityManager entityManager;

    public List<ContractDTO> getContractInfoByCSMRSN(BigInteger csmrSn){
        String sql = "복잡한 sql 쿼리문~~~"

        return entityManager.createNativeQuery(sql, "contractDTOMapping")
                .setParameter("csmrSn", csmrSn)
                .getResultList();
    }

    public List<ex> SelectContractById(String Id) {
        Optional<ex> contractOptional= krca_cntt_i_repo.findById(Id);
        List<ex> contract = new ArrayList<>();// List수정

        if (contractOptional.isPresent()) {
            logger.info("contractOptional.get() "+contractOptional.get());
            contract.add(contractOptional.get());
            return contract;
        } else {
            return contract;
        }
    } //성공






}
profile
응애 나 애기 개발자

0개의 댓글