[Java] Spring Boot 프로젝트에서 MyBatis와 JPA를 함께 사용하는 방법과 오류 해결 과정

2025. 8. 3. 04:35·개발 (Development)/Java

Spring Boot 2.5.5, Java 11, Maven, MyBatis 기반의 프로젝트에 JPA를 추가하면서 겪은 설정 및 오류 해결 과정을 정리합니다.
MyBatis와 JPA를 병행하고자 할 때 주의해야 할 설정 방식과 실제 발생했던 오류의 원인을 함께 소개합니다.

프로젝트 환경

  • Spring Boot: 2.5.5
  • Java: 11
  • 빌드 도구: Maven
  • ORM 프레임워크: MyBatis (기존), JPA (추가)
  • 데이터베이스: PostgreSQL

1. JPA 기본 설정 방법

1-1. Maven 의존성 추가

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <scope>runtime</scope>
</dependency>

1-2. application.yml 설정 예시

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/sample_db
    username: dbuser
    password: dbpass
    driver-class-name: org.postgresql.Driver

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect

1-3. Entity 및 Repository 구성

@Entity
@Table(name = "log_data")
@IdClass(LogDataId.class)
public class LogData {

    @Id
    @Column(name = "log_time")
    private String logTime;

    @Id
    @Column(name = "source_id")
    private String sourceId;

    @Column(name = "score_value")
    private Double scoreValue;

    @Column(name = "meta_info")
    private String metaInfo;

    @Column(name = "category_name")
    private String categoryName;

    @Column(name = "category_rate")
    private Double categoryRate;

    @Column(name = "type_name")
    private String typeName;

    @Column(name = "type_value")
    private String typeValue;

    @Column(name = "factor_name")
    private String factorName;

    @Column(name = "factor_ratio")
    private Double factorRatio;
}
public class LogDataId implements Serializable {
    private String logTime;
    private String sourceId;

    public LogDataId() {}

    public LogDataId(String logTime, String sourceId) {
        this.logTime = logTime;
        this.sourceId = sourceId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof LogDataId)) return false;
        LogDataId that = (LogDataId) o;
        return Objects.equals(logTime, that.logTime) &&
               Objects.equals(sourceId, that.sourceId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(logTime, sourceId);
    }
}
public interface LogDataRepository extends JpaRepository<LogData, LogDataId> {
}

1-4. 애플리케이션 클래스 설정

@SpringBootApplication
@EnableJpaRepositories("com.example.jpa.repository")
@EntityScan("com.example.jpa.entity")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2. 발생했던 오류와 원인

오류 메시지 예시

IllegalArgumentException: Not a managed type: class com.example.jpa.entity.LogData

주요 원인

원인 설명
@Id 없음 JPA는 반드시 @Id 또는 복합키 설정 필요
@EntityScan 누락 Entity 클래스의 패키지가 스캔되지 않음
EntityManager 설정 누락 MyBatis의 데이터소스가 우선 적용되어 JPA의 EntityManager가 초기화되지 않음

3. 해결 방법 – JPA 수동 구성

MyBatis 전용 설정이 존재하는 프로젝트에서는 JPA가 정상 작동하지 않을 수 있습니다. 이 경우, JPA 전용 설정 클래스를 명시적으로 구성해 충돌을 방지할 수 있습니다.

@Configuration
@EnableJpaRepositories(
  basePackages = "com.example.jpa.repository",
  entityManagerFactoryRef = "entityManagerFactory",
  transactionManagerRef = "transactionManager"
)
public class JpaDatabaseConfig {

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan("com.example.jpa.entity");

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);

        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", "validate");
        properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");

        em.setJpaPropertyMap(properties);
        return em;
    }

    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager(entityManagerFactory().getObject());
    }
}

정리

  • JPA를 사용할 때는 반드시 @Entity와 @Id를 포함한 클래스 구조를 갖추어야 합니다.
  • MyBatis와 함께 사용할 경우에는 각각의 데이터소스, 트랜잭션, 매퍼 패키지를 명확하게 분리해야 안정적으로 작동합니다.
  • Spring Boot의 자동 구성에 의존하기보다, 직접 EntityManagerFactory와 TransactionManager를 명시하는 방식이 더 안정적입니다.

결론

MyBatis 기반 프로젝트에 JPA를 추가하는 과정에서 충돌이나 예외가 발생할 수 있지만,
설정 클래스를 명시적으로 분리하고 엔티티 구조를 정확히 구성하면 MyBatis와 JPA를 병행하여 안정적으로 운영할 수 있습니다.
JPA를 점진적으로 도입하거나 혼합 구조로 개발하는 프로젝트에서는 이와 같은 구성이 큰 도움이 됩니다.

반응형

'개발 (Development) > Java' 카테고리의 다른 글

[Java] MyBatis와 JPA 속도 비교: 어떤 상황에 어떤 선택이 더 나을까?  (0) 2025.08.03
[Java] MyBatis만 쓰던 내가 JPA를 처음 접했을 때 이해한 구조 정리  (0) 2025.08.03
[Java] Spring Boot 2.x + Java 11 환경에서 JPA Native Query와 DTO 매핑 문제 해결 기록  (4) 2025.08.03
[Java] PostgreSQL의 timestamptz를 Java MyBatis에서 Instant로 받는 방법  (2) 2025.07.28
[Java] ISO 8601 형식의 시간 출력하기 (현재 시간과 과거 시간 구하기)  (2) 2025.07.20
'개발 (Development)/Java' 카테고리의 다른 글
  • [Java] MyBatis와 JPA 속도 비교: 어떤 상황에 어떤 선택이 더 나을까?
  • [Java] MyBatis만 쓰던 내가 JPA를 처음 접했을 때 이해한 구조 정리
  • [Java] Spring Boot 2.x + Java 11 환경에서 JPA Native Query와 DTO 매핑 문제 해결 기록
  • [Java] PostgreSQL의 timestamptz를 Java MyBatis에서 Instant로 받는 방법
LoopThinker
LoopThinker
모르는 것을 알아가고, 아는 것을 더 깊게 파고드는 공간
  • LoopThinker
    CodeMemoir
    LoopThinker
  • 전체
    오늘
    어제
    • 분류 전체보기 (216)
      • 개발 (Development) (151)
        • Algorithm (1)
        • Angular (1)
        • AWS (4)
        • DeepSeek (2)
        • Docker (7)
        • Git (3)
        • Java (30)
        • JavaScript (4)
        • Kafka (5)
        • Kubernetes (4)
        • Linux (6)
        • PostgreSQL (37)
        • Python (26)
        • React (3)
        • TypeScript (3)
        • Vue.js (5)
        • General (10)
      • 데이터 분석 (Data Analysis) (1)
      • 알고리즘 문제 풀이 (Problem Solving.. (27)
      • 자격증 (Certifications) (24)
        • ADsP (14)
        • 정보처리기사 (4)
        • Linux Master (5)
        • SQLD (1)
      • 기술 동향 (Tech Trends) (10)
      • 기타 (Others) (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Kubernetes
    리눅스 마스터 2급 2차
    docker
    백준자바
    deepseek
    springboot
    백준온라인저지
    JSON
    java
    백준
    PostgreSQL
    Vue.js
    javascript
    백준알고리즘
    Kafka
    typescript
    python
    자바
    리눅스 마스터 2급
    AWS
    ADsP
    Linux master
    Linux
    DevOps
    timescaledb
    데이터분석
    JPA
    MyBatis
    오답노트
    pandas
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
LoopThinker
[Java] Spring Boot 프로젝트에서 MyBatis와 JPA를 함께 사용하는 방법과 오류 해결 과정
상단으로

티스토리툴바