ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Project Config] Spring에 Mybatis 혹은 JPA 연동하기
    개발/개발환경구축 2022. 11. 30. 18:22

     

    +2020-12-12 jpa 연동 관련 pom 작성 오류를 수정 , 방언관련 수정

    +2020-12-13 jpa base-packege 관련 정보를 추가, MyBatis 의 Path 관련 정보 추가

    +2020-12-14 jpa auto create 관련 오류정보를 추가


    1.MyBatis

     

    ①pom.xml 에 의존을 추가해줍니다.

    더보기

    <dependency>
        <groupId>mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
    </dependency>

     


    ②classpath 에 디비 접속 관련 정보를 적은 프로퍼티를 작성합니다.

     

    classpath: 는 Eclips 등의 IDE에서 설정한 경로를 의미합니다.

    Eclipes 를 예시로 들자면 프로젝트 우클릭 - 속성 - Java Build Path 에 해당하는 경로들중에 한곳을 의미하므로 

    작성한 파일을 읽어 들이기 위해선 해당하는 경로들중 한 곳에 위치할 필요가 있습니다.

    작성자는 AddFolder버튼으로 webapp 경로를 추가한 뒤, webapp 경로 안에 프로퍼티를 작성했습니다.

     

    dataconfig.properties

    더보기
    db.driver=myDriver
    db.url=myUrl
    db.username=myName
    db.password=myPass

     

    자신이 쓰는 url , driver 관련 정보는

    카테고리 마지막 부분을 참고하세요

     


    classpath 에 mybatis-configuration.xml 를 작성합니다.

     

    mybatis-configuration.xml

    더보기
    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <configuration>
    <typeAliases>
    <typeAlias type="package.DTO" alias="DTOName"></typeAlias>
    <!--package.DTO 의 패키지 명을 DTOName 이라 칭함 -->
    </typeAliases>

    <properties resource=“classpath:/dataconfig.properties”/>

    <environments default="development">
    <environment id="development">
    <transactionManager type="JDBC"></transactionManager>

    <dataSource type="POOLED">
    <property name="driver" value=${db.driver}></property><!--$는 따옴표없음 #은 따옴표 있음-->
    <property name="url" value=${db.url}></property>
    <property name="username" value=${db.name}></property>
    <property name="password" value=${db.pass}></property>
    </dataSource>

    </environment>
    </environments>

    <mappers> <mapper resource="/mybatis-mapper.xml"/> </mappers>
    </configuration>

    classpath 에 mybatis-mapper.xml 를 작성합니다.

    ※접은 글은 어디 까지나 작성예시 입니다.

     

    mybatis-mapper.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="ExampleNameSpace">

    <delete id="deleteN">  <![CDATA[delete from table_psd where idx = #{idx}   ]]></delete>

    <update id="updateN" parameterType="DTOName" resultType="java.util.HashMap">
    UPDATE TABLE_PSD SET NAME = #{name} <!--DTOName 안에있는 인스턴스-->WHERE IDX = #{idx} 
    </update>

    </mapper>

    ⑤작성한 mapper와 config 파일로 Configuration.xml 에 Bean을 만들어 등록합니다.

    더보기

     

    configuration 에서 프로퍼티를 읽는 방법에 호환성 문제가 있어 나눠서 씁니다.

     

    스프링 3.1이상

    Beans 의 xmlns:context 속성 안에
    xmlns:context= "http://www.springframework.org/schema/context" 과xsi:schemaLocation= "http://www.springframework.org/schema/context/spring-context-자신의버전.xsd"
    를 추가한뒤 
    >
    <context:property-placeholder location="classpath:/dataconfig.properties" />를 작성해 줍니다.

     

    전체 공용

    <bean class="org.springframwork.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
    <list>
    <value>classpath:/dataconfig.properties</value>
    </list>
    </property>
    </bean>

     

     

    이제 프로퍼티를 읽어서 사용해줍니다.

     

    <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driver}"/>
    <property name="url" value="${db.url}"/>
    <property name="username" value="${db.username}"/>
    <property name="password" value="${db.password}"/>
    </bean>

    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionfactory">
    <property name="dataSource" ref="datasource"></property>
    <property name="mapperLocations" value="classpath:/*.xml"></property><!--mapper 들을 읽어옴 -->
    <property name="configLocation" value="classpath:/mybatis-configuration.xml"></property>
    </bean>

     

    xml로 configuration 을 작성하는 방법을 모르신다면 여기

    마지막 항목에 있는 configuration.xml 을 참고해 주세요.

    @ImportResource({"classpath:/configuration.xml"})

    를 통해서 해당 내용물을 읽어올 수 있습니다.


    2.JPA

     

    ①pom.xml 에 의존을 추가해줍니다.

    더보기
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>    
        <version>2.0.5.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.32</version>
    </dependency> <!--위의 spring data jpa 와 호환되는 버전일 필요가 있음--> 

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.10.Final</version> <!-- 호환 관련 오류로 5.2.10.Final로 수정 2022-12-13 -->
    </dependency>

    <!--QueryDSL관련-->
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <version>4.1.4</version>
    </dependency>

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>4.1.4</version>
        <scope>provided</scope>
    </dependency>


    ②configuration.xml 에 설정을 추가합니다.

    더보기
    <beans 내부에 추가
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 기존 구문 아래로 추가
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"


    xmlns:jpa
    ="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    >

    <jpa:repositories base-package="패키지경로.패키지" />

    </beans>

     

     

    패키지경로.패키지은 JpaRepository를 상속받은 인터페이스들의 위치를 의미합니다.

    @Repository 를 달지 않고도 경로에있는 상속받은 객체들은 모두 빈으로 등록됩니다.

     

    다만 ,  이 문구가 원인이 되어 오류가 발생할 수 있습니다.

    오류들에 대한 확인은 아래 닫힌 글을 확인해주세요.

     

    내용과 별개로.xml로 configuration 을 작성하는 방법을 모르신다면 여기

    마지막 항목에 있는 configuration.xml  참고해 주세요.

    @ImportResource({"classpath:/configuration.xml"})

    를 통해서 해당 내용물을 읽어올 수 있습니다.

     

    +관련 오류

    더보기
    1.만약 커스텀 JpaRepository 를 extends 해서 사용한다면
    CustomRepository 와 CustomRepositoryImpl 가 같은 패키지 안에 존재하는지 확인해주세요.

    2.TransactionManager 를 아직 Bean으로 등록하지 않았거나 못읽었을 때 해당 구문은 예외를 던집니다.

    3.@WebMvcTest , @Test 에서 사용할 경우 2번의 bean을 읽어 들이지 못함에 따른 예외를 던집니다.

    ③pom.xml 에 플러그인을 추가합니다.

    더보기

    build - plugins 에 추가합니다.

    <plugin>
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
    <execution>
    <goals>
    <goal>process</goal>
    </goals>
    <configuration>
    <outputDirectory>Qclass가 생성될 임의 지정 packagePath</outputDirectory>
    <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
    </configuration>
    </execution>
    </executions>
    </plugin>

     

    엔티티객체를 바탕으로 Q클래스를 생성해주는 설정입니다.


    ④webapp 안에 META-INF폴더를 만들고 안에 persistence.xml을 작성합니다.

     

    persistence.xml

    더보기
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1"> <!-- DB당 영속성 한개 -->
    <persistence-unit name="anyindexnaming" transaction-type="RESOURCE_LOCAL">
    <properties>

    <!--<property name="hibernate.dialect" value="DB에 맞는 방언" />-->
    <!--자신의 DB버전과 종류에맞는 설정이 필요-->
    <!--해당 DB에서만 제공하는 방언을 설정함-->
    <!--다만, 사용하는 jdbc에 맞춰서 스스로 맞춰지기 때문에 웬만하면 적지말것-->
    <!--스스로 맞춰주는 DB가 아닐경우 맞는 설정을 반드시 찾아서 해야함-->

    <property name="hibernate.show_sql" value="true" /> <!-- hibernate가 실행한 SQL을 출력 -->
    <property name="hibernate.format_sql" value="true" /> <!-- SQL 출력 시 정돈된 출력 -->
    <property name="hibernate.use_sql_comments" value="true" /> <!-- 쿼리 출력 시 주석도 함께 출력 -->
    <property name="hibernate.id.new_generator_mappings" value="true" /> <!--자동키 생성 사용시 필요-->

    <!--스키마 자동 생성<property name="hibernate.hbm2ddl.auto" value="create" />-->

    </properties>
    </persistence-unit>
    </persistence>

     

    hibernate.dialect

     

    Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set 오류가 발생한다면

     

    방언을 찾기전에 먼저 JDBC를 통해서 자신의 계정정보가 제대로 일치하는지,

    DB에 접속이 가능한 방화벽 설정을 해놨으며

    접속하는 계정이 데이터베이스에 접근할 수 있는 권한을 지니고 있는지 먼저 확인하시길 바랍니다.

     

    만약 접속이 확인된 후에 본 문구가 지속 된다면 그 후에 구글링으로 자신에게 적합한 DB 방언을 찾아줍니다.

     

     

    ibernate.hbm2ddl.auto

     

    스키마 자동 생성기능은 create 사용시 기존 내용물을 지우고 생성하며,

    이를 원하지 않을시 update를 사용합니다.

     

    만약 DB에서 데이터를 매칭해서 읽어오는 것이 목적이라면

    value = "validate" 를 통해 서로의 테이블이 일치하는가만 확인할 수 있습니다.

    단, 예외를 던지면서 실행을 막는 것은 둘째 치고 그 원인은 안가르쳐 줍니다.

    옵션 사용시 Entity 클래스를 직렬화할 필요가 있습니다.

     

     

    transaction-type="RESOURCE_LOCAL"

     

    spring data jpa 를 사용하기 위해서 (JpaRepository) 기본적으로 설정해야되는 옵션입니다.

    작성하지 않으면 트랜젝션 오픈 문제로 JpaRepository를 사용할 수 없습니다.

     


    ⑤configuration.xml에 EntityManagerFactory를 빈으로 등록합니다.

    더보기

     

    본 내용중에는 ${프로퍼티}를 사용합니다.

    프로퍼티 사용에 대해서는 MyBatis , 를 참고해주세요.

    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${db.driver}"/>
    <property name="url" value="${db.url}"/>
    <property name="username" value="${db.username}"/>
    <property name="password" value="${db.password}"/>
    </bean> <!-- datasource 추가, EntityManagerFactory 의 인자 2번 -->

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    <!--EntityManagerFactory 의 인자 2번-->

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    </bean> <!--EntityManagerFactory 를 빈 등록-->

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean> <!--EntityManager 를 빈 등록 -->

    <tx:annotation-driven transaction-manager="transactionManager" /> <!--트랜젝션 사용-->

    <!--<context:component-scan base-package="com.spring.jpa">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan> --> <!--JPA 어노테이션들을 컴포넌트 스캔 , 선택사항. -->
    <!--사용하시려면 beans 내부에 xmlns:context="http://www.springframework.org/schema/context" 를 추가해야 합니다. -->

    +jpa 관련 오류 문제

     

    솔직히.. 예외를 이렇게 대충 던지는 api는 처음봅니다.

    그래서 사용상 대표적인 오류 두가지 를 설명합니다.

     

    Unable to access TransactionManager or UserTransaction to make physical transaction delegate

    >JPQL 작성에 틀린 부분이 있을 때, 커스텀 JPARepository 의 Impl 를 인식을 못할 때 발생합니다.

     

    Error creating bean with name 'entityManagerFactory' defined in class path resource [config/configuration.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: jpasystem] Unable to build Hibernate SessionFactory 이유는 알아서 찾으시고 아무튼 빈 생성에 실패했다는 뜻을 지닌 개노답 문구

    >

    1.database 로그인 실패

    2.database 권한 없음

    3.JDBC가 JPA와 호환되지 않음 (더 낮은 버전의 JDBC가 필요)

    4.컬럼명 중복매칭

    5.<property name="hibernate.hbm2ddl.auto" value="???" />

    위 옵션 사용시 엔티티가 DB에 존재하는 테이블과 서로 일치하거나 호환되지않음

    →데이터가 중요하지 않다면 create로 테이블초기화를 한번 돌리는 것을 추천하며, 혹은 위 항목을 아예 쓰지 마세요.

     

     

    댓글

개발에 관심을 가지는 블로그