본문 바로가기

JPA

JPA 와 Mybatis 같이 사용하기

728x90
반응형
SMALL

안녕하세요.

 

JPA 는 ORM 으로 단순 CRUD 처리에 대해 편리하게 해주는데요.

 

실무에서 정산 쿼리나, 복잡한 여러 조인이 필요한 쿼리들이 있을 때에는, JPA 보단 mybatis를 혼용해서 쓴다고 합니다.

 

그래서 지금 JPA 와 MyBatis 를 혼용하여 쓰고, 한 트랜잭션 안에 잘 묶여있는지 확인 테스트 까지 해보겠습니다.

 

데이터베이스는 h2 database 를 사용하겠습니다. (경량용 디비로 테스트 하기에 적합함.)

h2사용법

 

H2 Database 란? 그리고 사용법?

H2 Database 란? H2는 자바로 작성된 관계형 데이터베이스 관리 시스템이다. 장점 따로 설치가 필요없다 용량이 매우 가볍다 웹용 콘솔(쿼리툴) 제공하여 개발용 로컬DB로 사용 용이 특징 JAVA로 작성

yjkim-dev.tistory.com

 

먼저 Springboot 프로젝트를 만들어 준 후,

의존성 주입을 해줍니다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.2'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

의존성 정보는 이렇게 됩니다.

- spring data jpa

- mybatis

- h2

 

 

이제 application.yml 에 jpa 및 h2 database를 사용하기 위한 기본 설정을 해보겠습니다.

spring:
  h2:
    console:
      enabled: true
      path: /mix
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:tcp://localhost/~/mix
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        show_sql: true
        format_sql: true

이렇게 하면 h2 연동 및 jpa 를 사용하겠다는 설정이 완료되었습니다.

 

h2 연동 되어 jpa를 사용하겠다는 설정이 되었는지 확인이 필요하다고요? 확인해봅시다.

 

MemberRepository.java

JPA 사용하기 위해 레파지토리 세팅 합니다.

public interface MemberRepository extends JpaRepository<Member,Long> {
}

Member.java 엔티티를 만들어줍시다.

@Entity
@Getter
public class Member {
    @Id@GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String nickName;

MemberController.java 테스트 한번 해봅시다.

@RestController
@RequiredArgsConstructor
@Slf4j
public class MemberController {

    private final MemberRepository memberRepository;
  

    //jpa - insert
    @PostMapping("/test")
    public void addMemberJPA(){
        Member member = new Member();
        member.addMember("김영재","닉네임");
        memberRepository.save(member);
    }

addMember 메소드가 필요하니, Member에 아래 코드를 추가해줍시다.

@Entity
@Getter
public class Member {
    @Id@GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String nickName;

    public void addMember(String name, String nickName) {
        this.name = name;
        this.nickName = nickName;
    }

 

콘솔에 보면

hibernate가 쿼리를 만들어 줬네요.

 

jpa가 정상적으로 연동되어 h2에 담겼다는 걸 알수 있습니다.

 

이제 jpa 연동을 확인 하였으니, mybatis를 연동 해 봅시다.

 

보통 jpa는

controller -> service -> repository 

 

mybatis는

controller -> service -> mapper -> xml

 

순서로 이루어져있습니다.

 

 

먼저 mybatis 설정을 위해 config를 작성해 줍시다.

 

 

MybatisConfig.java (sql session 에 대한 관련 기능을 대신해주는 sqlSessionFactory Bean을 생성합니다.)


@Configuration
@MapperScan(basePackages={"com.example.mybatismixjpa.mapper"}, sqlSessionFactoryRef="sqlSessionFactory",sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisConfig {


    @Bean(name="sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage("com.example.mybatismixjpa");
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mybatis/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

}

ln 2: basePackages에 Mapper 인터페이스 패키지 위치를 작성합니다.
ln 6: 기존에 이용하고 있던 dataSource를 주입받습니다. 현재 주입하는 dataSource는 application.yml 프로퍼티에 설정한 DB 정보를 통해 자동 생성된 dataSource입니다.
ln 9: setTypeAliasesPackage 설정을 통해 엔티티의 패키지 이름을 생략할 수 있도록 합니다.
ln 10: resources 아래의 mapper 폴더 내의 *-mapper.xml 파일들을 SQL Map XML파일로 설정합니다.

 

 

기본 mybatis 설정이 끝입니다.

이제 다시

MemberController.java 로 가서 mybatis 연동을 해줍시다.

private final MemberMapper mapper;
@GetMapping("/test2")
public List<Member> selectMemberMybatis(){
    List<Member> results = mapper.findById();
    log.info("results : {}" , results);
    return results;
}

 

MemberMapper.java

@Mapper
public interface MemberMapper {

   List<Member> findById();

}

 

이제 중요한 XML를 작성할 차례입니다. (실제 쿼리를 작성하는 부분입니다.)

경로는

resources -> mybatis -> MemberMapper.xml 입니다.

 

MemberMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mybatismixjpa.mapper.MemberMapper">
    <select id="findById" resultType="Member">
        SELECT id,
               name,
               nick_name as nickName
        from member;
    </select>

결과를 보면

mybatis로 정상적으로 조회가 되는 것을 확인 할 수 있습니다.

 

 

이렇게 jpa 와 mybatis를 혼용해서 사용해 보았습니다.

 

보통 단순한 쿼리는 jpa 를 사용하며, 조금 더 복잡해지면 querydsl 를 사용하여 해결을 할 수 있지만,

엄청 복잡한 쿼리(정산 쿼리)나 그런 쿼리들은 mybatis가 효율적이라고 하네요.

 

//jpa - insert
@PostMapping("/test")
public void addMemberJPA(){
    Member member = new Member();
    member.addMember("김영재","닉네임");
    memberRepository.save(member);
}
//jpa - select
@GetMapping("/test")
public List<Member> selectMemberJPA(){
    return memberRepository.findAll();
}
//jpa - update
@PutMapping("/test")
@Transactional
public void updateMemberJPA(){
    MemberUpdateDto memberUpdateDto = new MemberUpdateDto(3L,"수정자김영재");
    Member member = memberRepository.findById(memberUpdateDto.getId()).get();
    member.updateMember(memberUpdateDto);
}
//jpa - delete
@DeleteMapping("/test")
public void deleteMemberJPA(){
    MemberUpdateDto memberUpdateDto = new MemberUpdateDto(3L,"수정자김영재");
    Member member = memberRepository.findById(memberUpdateDto.getId()).get();
    memberRepository.delete(member);
}


//mybatis - select
@GetMapping("/test2")
public List<Member> selectMemberMybatis(){
    List<Member> results = mapper.findById();
    log.info("results : {}" , results);
    return results;
}
//mybatis - insert
@PostMapping("/test2")
public void addMemberMybatis(){
    Member member = new Member();
    member.addMember("김영재-마이바티스","닉네임");
    mapper.addMember(member);
}
//mybatis - update
@PutMapping("/test2")
public void updateMemberMybatis(){
    MemberUpdateDto memberUpdateDto = new MemberUpdateDto(3L,"수정자김영재");

    mapper.updateMember(memberUpdateDto);
}
//mybatis - delete
@DeleteMapping("/test2")
public void deleteMemberMybatis(){
    mapper.deleteMember(1L);
}

 

jpa 와 mybatis 에 대해 각자 CRUD 를 만들어봤는데요.

jpa가 확실히 편리하긴 하네요.

복잡한 쿼리를 위할때만 mybatis를 쓰자!!

 

위의 테스트를 해보니 둘다 제대로 값 나오네요.

 

잘못된 내용이 있다면 댓글 달아주시길 바랍니다.

 

감사합니다.

728x90
반응형
LIST