가희의자기개발블로그

자바 API 본문

백엔드/myBatis

자바 API

가희gahui 2020. 7. 6. 12:41
반응형

마이바티스 자바 API는 JDBC와 비교해보면 코드를 단순하고 깔끔하게 만든다. 이해하기 쉬워서 유지보수도 쉽다.

1_디렉터리 구조

자바 API를 살펴보기 전에 디렉터리 구조에 대해 전반적으로 이해하는 것이 중요하다. 마이바티스는 매우 유연하고 파일을 사용해서 어떤 것도 할 수 있다. 하지만 프레임워크이기 때문에 선호하는 방법이 있다.

 

전형적인 애플리 케이션 디렌터리 구조를 살펴보자

/my_application
  /bin
  /devlib
  /lib                <-- 마이바티스 *.jar 파일이 여기 있다.
  /src
    /org/myapp/
      /action
      /data           <-- 마이바티스 산출물이 여기 있다. Mapper 클래스, XML 설정, XML 매핑 파일들
        /mybatis-config.xml
        /BlogMapper.java
        /BlogMapper.xml
      /model
      /service
      /view
    /properties       <-- XML 설정파일에 포함된 프로퍼티들이 여기 있다.
  /test
    /org/myapp/
      /action
      /data
      /model
      /service
      /view
    /properties
  /web
    /WEB-INF
      /web.xml

이 구조는 선호되는 형태이지 따라야할 요구사항이 아님을 기억하자. 

 

2_SqlSessions

마이바티스를 사용하기 위한 기본적인 자바 인터페이스는 SqlSession이다. 이 인터페이스를 통해 명령어를 실행하고 매퍼를 얻으며 트랜잭션을 관리 할 수 있다. 먼저 SqlSession의 인스턴스를 만드는 방법을 배워보자. SqlSession은 SqlSessionFactory인스턴스를 사용해서 만든다. SqlSessionFactory자체는 XML, 애노테이션 또는 자바 설정에서 SqlSessionFactory를 생성할 수 있는 SqlSessionFactoryBuilder를 통해 만들어진다. 

 

2_1_SqlSessionFactoryBuilder

SqlSessionFactoryBuilder는 5개의 build()메소드를 가진다. 각각은 서로 다른 소스에서 SqlSessionFactory을 빌드한다. 

SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)

처음 4개의 메소드가 가장 공통적이다. xml문서를 나타내는 Reader인스턴스를 가진다. 선택적으로 사용가능한 프로퍼티는 environment와 properties이다. environment는 데이터소스와 트랜잭션 관리자를 포함하여 로드할 환경을 판단한다. 예를들면,

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
        ...
    <dataSource type="POOLED">
        ...
  </environment>
  <environment id="production">
    <transactionManager type="MANAGED">
        ...
    <dataSource type="JNDI">
        ...
  </environment>
</environments>

environment파라미터를 가진 메소드를 호출한다면 마이바티스는 사용할 환경을 위한 설정을 사용할 것이다. 물론 잘못된 환경 설정을 사용하면 에러를 보게 될것이다. environment파라미터를 가지지 않는 메소드 중 하나를 호출한다면 디폴트 환경이 사용될 것이다. 

properties인스턴스를 가진 메소드를 호출하면 마이바티스는 프로퍼티들을 로드해서 설정에서 사용가능한 부분을 사용할 것이다. 프로퍼티들은 ${propName}와 같은 문법을 사용해서 설정의 값으로 대체될 수 있다.

프로퍼티들은 SqlMapConfig.xml파일에서 사용되거나 직접 명시할 수 있다. 그러므로 프로퍼티들의 우선순위를 이해하는 것이 중요하다. 

 

프로퍼티가 한개 이상 존재한다면 마이바티스는 일정한 순서로 로드한다. 

  • properties엘리먼트에 명시된 속성을 가장 먼저 읽는다.
  • properties엘리먼트의 클래스패스 자원이나 url속성으로 부터 로드된 속성을 두번째로 읽는다. 그래서 이미 읽은 값이 있다면 덮어쓴다.
  • 마지막으로 메소드 파라미터로 전달된 속성을 읽는다. 앞서 로드된 값을 덮어쓴다.

그래서 가장 우선순위가 높은 속성은 메소드의 파라미터로 전달된 값이고 그 다음은 자원및 url속성이고 마지막은 properties엘리먼트에 명시된 값이다.

 

요약해보면 처음 4개의 메소드는 사실 같지만 environment 그리고/또는 properties에 명시한 값을 오버라이드한다.

mybatis-config.xml파일에서 SqlSessionFactory를 빌드하는 예제이다. 

String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

 

Resources 유틸리티 클래스를 사용하고 있는 것을 주의깊게 보면 된다. 이 클래스는 org.apache.ibatis.io 패키지에 있다. Resources 클래스는 그 이름이 나타내는 것처럼 클래스패스나 파일 시스템 또는 웹 URL 에서 자원으로 로드하도록 해준다. IDE를 통해 클래스의 소스 코드를 보는 것으로 유용한 메소드를 보게 될 것이다.

 

마지막 build메소드는 Configuration 의 인스턴스를 가진다. Configuration클래스는 SqlSessionFactory인스턴스에 대해 알 필요가 있는 모든 것으로 가지고 있다. Configuration클래스는 SQLMap을 찾거나 관리하는 것을 포함하여 설정을 살펴보기 위해 유용하다. Configuration클래스는 모든 설정을 처리할 수 있으며 자바 API로 나타낼 수 있다. SqlSessionFactory를 생성하기 위해 Configuration인스턴스를 build()메소드에 전달하는 예제이다. 

DataSource dataSource = BaseDataTest.createBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();

Environment environment = new Environment("development", transactionFactory, dataSource);

Configuration configuration = new Configuration(environment);
configuration.setLazyLoadingEnabled(true);
configuration.setEnhancementEnabled(true);
configuration.getTypeAliasRegistry().registerAlias(Blog.class);
configuration.getTypeAliasRegistry().registerAlias(Post.class);
configuration.getTypeAliasRegistry().registerAlias(Author.class);
configuration.addMapper(BoundBlogMapper.class);
configuration.addMapper(BoundAuthorMapper.class);

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);

 

2_2_SqlSessionFactory

SqlSessionFactory는 SqlSession 인스턴스를 생성하기 위해 사용할 수 있는 6개의 메소드를 가지고 있다. 6개의 메소드가 선택해서 사용하는 것들을 보자.

  • Transacton: 세션에서 트랜잭션 스코프 또는 자동 커핏을 사용하고 싶은가?
  • Connection: 설정된 DataSource에서 Connection을 회득하고 싶은가?
  • Execution : PreparedStatements 그리고/또는 배치 업데이트를 재사용하고 싶은가?

오버로드된 메소드인 openSession()이 3가지를 적절히 혼합해서 사용할 수 있다.

 

SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();

파라미터를 가지지 않는 디폴트 openSession()메소드는 다음과 같은 성격을 가진 SqlSession을 만들것이다.

 

  • 트랜잭션 스코프는 시작될 것이다.
  • Connection 객체는 활성화된 환경에 의해 설정된 DataSource인스턴스를 획득할 것이다.
  • 트랜잭션 격리 레벨은 드라이버나 데이터소스가 디폴트로 제공하는 옵션을 사용할 것이다.
  • PrepartedStatements는 재사용되지 않을 것이다. 그리고 update또한 배치처리되지 않을 것이다. 

메소드 대부분은 그 이름과 파라미터가 그 역할을 충분히 설명한다. 자동커밋을 활성화하기 위해서 autoCommit파라미터에 true값을 설정하면 된다. 자체적인 커넥션을 제공하기 위해서는 connection파라미터에 Conenction인스턴스를 설정한다. 

 

Connection과 autoCommit둘다 설정하는 것을 오버라이드하지 않는다. 왜냐하면 마이바티스는 제공된 connection객체를 설정할때마다 현재 사용중인 것을 사용한다. 마이바티스는 TransactionIsolationLevel라고 불리는 트랜잭션 격리 레벨을 위한 자바 enum 래퍼를 사용한다. JDBC는 5가지를 지원한다. 

(NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE).

 

새롭게 보일수 있는 하나의 파라미터는 ExecutorType이다. enum으로는 3개의 값을 정의한다.

  • ExecutorType.SIMPLE: 이 타입의 실행자는 아무것도 하지 않는다. 구문 실행마다 새로운 PreparedStatement를 생성한다.
  • ExecutorType.REUSE: 이 타입의 실행자는 PreparedStatements를 재사용할 것이다.
  • ExecutorType.BATCH: 이 실행자는 모든 update구문을 배치처리하고 중간에 select 가 실행될 경우 필요하다면 경계를 표시한다. 이러한 과정은 행위를 좀더 이해하기 쉽게 하기 위함이다.

2_3_SqlSession

SqlSession인스턴스는 마이바티스에서 굉장히 강력한 클래스이다. 구문을 실행하고 트랜잭션을 커밋하거나 롤백하는 그리고 mapper인스턴스를 습득하기 위해 필요한 모든 메소드를 찾을 수 있다.

 

SqlSession에는 20개 이상의 메소드가 있다. 

 

2_3_1 구문을 실행하는 메소드

이 메소드들은 SQL매핑 XML파일에 정의된 SELECT, INSERT, UPDATE, DELETE구문을 실행하기 위해 사용된다. 메소드 이름 자체가 그 역할을 설명하도록 명명되었다. 메소드 각각은 구문의 ID와 파라미터 객체를 가진다. 

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

selectOne과 selectList의 차이점은 selectOne은 옺기 하나의 객체만을 리턴해야 한다는 것이다. 한개 이상을 리턴하거나 null이 리턴된다면 예외가 발생한다. 얼마나 많은 객체가 리턴될지 모른다면 selectList()를 사용한다. 객체의 존재여부를 체크하고 싶다면 개수를 리턴하는 방법이 더 좋다. selectMap은 결과 목록을 Map으로 변환하기위해 디자인된 특별한 경우이다. 이 경우 결과 객체의 프로퍼티 중 하나를 키로 사용하게 된다. 모드 구문이 파라미터를 필요로 하지는 않기 때문에 파라미터 객체를 요구하지 않는 형태로 오버로드 되었다. 

 

insert, update 그리고 delete 메소드에 의해 리턴되는 값은 실행된 구문에 의해 영향을 받은 레코드수를 표시한다.

<T> T selectOne(String statement)
<E> List<E> selectList(String statement)
<T> Cursor<T> selectCursor(String statement)
<K,V> Map<K,V> selectMap(String statement, String mapKey)
int insert(String statement)
int update(String statement)
int delete(String statement)

2_3_2 트랜잭션 제어 메소드

트랜잭션을 제어하기 위해 4개의 메소드가 있다. 물론 자동 커핏을 선택하였거나 외부 트랜잭션 관리자를 사용하면 영향이 없다. 어쨌는 Connection인스턴스에의해 관리되고 JDBC트랜잭션 관리자를 사용하면 4개의 메소드를 사용할 수 있다.

void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)

기본적으로 마이바티스는 INSERT, UPDATE, DELETE를 호출하여 데이터베이스가 변경된 것으로 감지하지 않는 한 실제로 커밋하지 않는다. 이러한 메소드 호출없이 변경되면 커밋된 것으로 보장하기 위해 COMMIT과 rollback메소드에 true값을 전달한다.

 

2_3_3 SqlSession은 반드시 닫아야한다.

sqlSession.close()

반드시 기억해야 하는 중요한 것은 당신이 열었던 세션을 닫아주는 것이다. 확실히 하기 위해 가장 좋은 방법은 다음과 같은 형태로 개발하는 것이다.

 

 

반응형

'백엔드 > myBatis' 카테고리의 다른 글

동적SQL  (0) 2020.07.04
Mapper XML파일  (0) 2020.07.04
매퍼 설정  (0) 2020.07.01
myBatis 시작하기  (0) 2020.06.30
myBatis 개념  (0) 2020.06.22
Comments