SqlSessionFactory

SqlSessionFactory 에서 만들어지는 SqlSession 객체가 담당한다.

그리고 SqlSession 객체를 생성하는 시점에 트랜잭션에 관련한 속성을 결정한다.

 

 

SqlSessionFactory class 가 제공하는 openSession()

1. openSession(): 마이바티스 설정 파일의 설정을 그대로 사용하는 바이바티스 객체 생성

2. openSession(boolean autoCommit): 마이바티스 설정을 그대로 사용하되 자동 커밋 여부를 변경함

3. openSession(Connection connection)
: 마이바티스 연결 정보를 갖는 커넥션 타입 객체를 피라미터로 전달해서 마이바티스 객체 생성
: 만들어진 객체만큼 연결 객체가 갖는 여러 정보를 생성 시점에 설정 가능
: 연결 정보를 직접 사용하기 때문에 "마이바티스와 별도로 트랜잭션 제어 가능"

4. openSession(TransactionIsolationLevel level)
: 트랜잭션 격리 레벨을 지정해서 마이바티스 객체를 생성

그 외에 여러 메소드가 있음

 

 

openSession 메소드를 사용해 객체를 생성하게 되면 다음과 같은 특징을 가지게 됩니다.

 

- 객체를 생성할 때마다 트랜잭션 시작

- 마이바티스 설정 파일로 데이터 소스 사용

- 트랜잭션 관련 격리 레벨이나 전파 설정은 설정한 값을 사용해 설정됨

 

 

 

트랜잭션을 처리하는 메소드

1. commit(): 데이터를 입력, 수정, 삭제한 내용을 데이터베이스에 물리적으로 반영 (마이바티스가 변경한적 있다고 판단해야 처리함)

2. commit(boolean force): 내부적으로 데이터를 변경한 적 있는지 판단하지 않고 무조건 처리함

3. rollback(): 트랜잭션 롤백해서 직전까지 데이터를 반영하지 않고 무시함 마이바티스가 변경한적 있다고 판단해야 처리함)

4. rollback(boolean force): 내부적으로 데이터를 변경한 적 있는지 판단하지 않고 무조건 처리함

 

 

 

 

WHERE 절이 OUTER JOIN에서 데이터를 누락시키는 주요 이유 중 하나는 OUTER JOIN의 작동 방식과 관련이 있습니다.

 

OUTER JOIN은 두 개 이상의 테이블을 연결할 때 사용되며,

특히 어느 한 쪽 테이블에 매칭되는 데이터가 없더라도 결과를 반환합니다.

이러한 특성 때문에 WHERE 절에서 조건을 지정하면 OUTER JOIN의 결과를 필터링할 수 있습니다.

 

그러면 왜 OUTER JOIN에서 데이터를 누락시키는지 살펴보겠습니다

 

ex.

SELECT d.deptno, sum(e.sal)
FROM dept d LEFT OUTER JOIN emp e
ON d.deptno = e.deptno
WHERE e.sal > 2000
GROUP BY d.deptno
ORDER BY d.deptno;

: 이런 경우 deptno 가 10, 20, 30에 값이 있고, deptno 40에 e.sal 값이 null일 때 deptno 40컬럼에 대한 데이터가 누락됩니다.

 

  1. NULL 값 필터링: OUTER JOIN에서 한 쪽 테이블과 매칭되는 데이터가 없는 경우, 해당 행의 다른 쪽 테이블의 열은 NULL 값을 가집니다. WHERE 절을 사용하여 NULL이 아닌 행만 선택하면, 데이터의 일부가 누락될 수 있습니다.
  2. 결과 제한: WHERE 절을 사용하여 결과를 필터링하면 OUTER JOIN 결과에서 특정 행을 제외할 수 있습니다. 예를 들어, WHERE 절에서 조건을 만족하지 않는 행을 필터링하면 OUTER JOIN 결과에 해당 행이 나타나지 않게 됩니다.
  3. 조인 조건: OUTER JOIN의 결과를 필터링하기 위해 WHERE 절에 조인 조건을 추가할 수 있습니다. 조인 조건을 만족하지 않는 행은 결과에서 제외됩니다.
  4. 의도한 필터링: 때로는 OUTER JOIN 결과를 일부 필터링하여 특정 데이터만 가져오기를 원할 수 있습니다. 이 경우 WHERE 절을 사용하여 결과를 원하는 대로 제한할 수 있습니다.

OUTER JOIN과 WHERE 절을 함께 사용할 때 주의해야 합니다.

데이터 누락을 방지하려면 OUTER JOIN 조건과 WHERE 절을 조심스럽게 설계해야 합니다. 원하는 결과를 얻기 위해 조건을 올바르게 설정하는 것이 중요합니다.

'mybatis' 카테고리의 다른 글

트랜잭션 관리  (0) 2023.09.14
mybatis associate, collection, alias  (0) 2023.09.12
마이바티스란? (과정 및 개요)  (0) 2023.09.10
Spring + MySQL + Mybatis  (0) 2023.08.17
Association

has one 관계를 형성하기 위함

 

 

Collection

has many 관계를 형성하기 위함

 

 

Mybatis 에서 관게를 정의하는 방법
  • Nested Select : 1번의 추가 Select 를 통한 데이터 검색
  • Nested Results : Join 을 통한 한 번에 데이터 검색

2번의 경우, association 태그 내에서 resultMap에 지정한 형태로 결과 값을 담게 된다.

 

 

도메인 관계

[User] 1:1 [Board]
[Apply] N:1 [Board]

@Data
public class User {
 private Long id;
 pirvate String name;
}

@Data
public class Board {
 private Long id;
 private String name;
 private User user;  // has one relation ( association )
 private List<Apply> apply; // has many relation ( collection )
}

public class Apply {
 private Long id;
 private Board board; // has one relation ( association )
 private User user; // has one relation ( association )
}

 

 

<mapper namespace="package.BoardRepo">    

    <resultMap id="userResultMap" type="package.users">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
    </resultMap>
    
    
    
    <resultMap id="BoardResultMap" type="package.Board">
    	<id column="board_id" property="id" jdbcType="BIGINT"/>
        <result column="board_name" property="name" jdbcType="VARCHAR"/>
        
        // nested Result
        <collection column="applys" property="applys" ofType="hashmap" javaType="list">
        	<id column="id" property="id" jdbcType="BIGINT"/>
            
            // nested Result
            <assocation property="board" resultMap="BoardResultMap"/>
            
            //nested Select
            <assocation column="user_id" property="user" select="selectUserById"/>
        </collection>

        // nested Result
        <assocation property="user" resultMap="userResultMap"/>
    </resultMap>
    
    
    
    <resultMap id="applyResultMap" type="package.applys">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <assocation property="board" resultMap="BoardResultMap"/>
        <assocation column="user_id" property="user" select="selectUserById"/>
    </resultMap>



    <select id="selectUserById" resultMap="UserResultMap2" parameterType="java.lang.Long">
        SELECT
            id, name
        FROM
            users
        WHERE
            id = #{id, jdbcType=BIGINT}
    </select>
</mapper>

 

  • <association property="user" resultMap="userResultMap"/>

이 의미는 Board 클래스에 User타입의 user 변수에 resultMap으로 선언한 userResultMap 형태의 값을 바인딩시킨다.

즉, user에 userResultMap의 값이 들어간다.

 

 

  • <assocation column="user_id" property="user" select="selectUserById"/>

이 의미는 해당 쿼리를 수행하기 전에 selectUserById 쿼리를 먼저 수행해준다.

 

 

 

${alias}

동적 SQL 쿼리를 작성할 때 사용하는 "플레이스 홀더" 이다.

이를 통해 SQL 일부를 "동적" 으로 생성하거나 피라미터로 값을 삽입 가능하다.

 

즉, '${alias}' 문법은 문자열 치환을 수행한다.

 

<select id="findUsersByAlias" parameterType="string" resultType="com.example.User">
  SELECT * FROM users WHERE alias = #{alias}
</select>

이 매퍼는 findUsersByAlias라는 메소드에서 alias라는 파라미터를 받아 테이블에서 alias에 해당하는 사용자를 검색한다.

 

이를 수행하는 코드:

 

String alias = "john_doe"; // 파라미터로 전달할 alias 값
User user = sqlSession.selectOne("findUsersByAlias", alias);

이렇게 실제로 alias라는 파라미터를 전달해야 합니다.

 

이는 동적 검색, 정렬 순서와 같이 일부 조건을 바꿔야 할 때 유용합니다.

 

 

'mybatis' 카테고리의 다른 글

트랜잭션 관리  (0) 2023.09.14
WHERE 절은 왜 OUTER JOIN 에서 데이터를 누락시키는가?  (0) 2023.09.13
마이바티스란? (과정 및 개요)  (0) 2023.09.10
Spring + MySQL + Mybatis  (0) 2023.08.17

개요

- 마이바티스는JDBC를 대체하는 Persistence Framework이다.

- 즉, 개발자는 SQL문을 작성하고 Mybatis는 JDBC를 사용해 실행한다. ( 아래에 과정을 참조 )

- ORM 프레임워크가 아닌 SQL 매퍼이다. ( ORM은 객체 간의 관계를 자동으로 설정해주지만 Mybatis는 명시 해줘야함 )

- 트랜잭션을 관리한다.

 

 

 

Mybatis를 왜 사용하는가?

- JDBC 코드를 작성하는 일에는 코드를 복사하고 붙쳐넣으며 많은 시간이 소요된다. 그리고 그만큼 오류도 빈번히 발생한다.

- 마이바티스는 객체 지향 언어인 자바에서 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 하도록 도와주는 프레임워크이다.

 

 

 

 

사용 과정

1. MySQL에 테이블을 생성한다.
2. Spring gradle에 Mybatis, Mysql Library를 위한 라이브러리를 작성하고 yml에 mybatis를 위한 설정을 해준다.
3. Mybatis를 활용하기 위해 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="kia.com.mybatistest.model.dao.UserMapper">

    <resultMap id="UserDto" type="kia.com.mybatistest.model.dto.UserDto">
        <result property="userId" column="user_id"/>
        <result property="userName" column="user_name"/>
        <result property="userEmail" column="user_email"/>
        <result property="userPassword" column="user_password"/>
        <result property="createAt" column="create_at"/>
        <result property="modifyAt" column="modify_at"/>
    </resultMap>

    <select id="findByIdAndPassword" resultType="kia.com.mybatistest.model.dto.UserDto">
        SELECT user_email, user_password
        FROM users
        WHERE user_email=#{userEmail}
          AND user_password=#{userPassword}
    </select>

    <select id="saveUser" resultMap="UserDto">
        INSERT INTO users(user_name, user_email, user_password, create_at, modify_at)
        VALUES (#{userName},
                #{userEmail},
                #{userPassword},
                DATE_FORMAT(#{createAt}, '%Y-%m-%d %H:%i:%s'),
                now()
                );
    </select>
</mapper>​

위 코드와 같이 Query문을 작성하고, resultMap을 활용해 객체 클래스와 같은 필드를 가진 Map을 만들어준다.
그리고 여기서 id값은 자바 메소드와 매핑된다.

4. 관련 DTO를 만들어준다.
5. 기능을 수행할 DAO를 만들어준다.

@Repository
@Mapper
public interface UserMapper {
    List<UserDto> getAllUserDataList();
    UserDto saveUser(UserDto userDto);
    UserDto findById(Long id);
    UserDto findByIdAndPassword(LoginUserDto loginUserDto);
}

이와 같이 @Mapper 어노테이션을 통해서 위의 xml 네이밍과 매핑이 되서 서비스 클래스에서 사용할 수 있게된다.

6. 위의 매퍼를 활용해 레포지토리와 서비스를 만들어준다.

 

 

'mybatis' 카테고리의 다른 글

트랜잭션 관리  (0) 2023.09.14
WHERE 절은 왜 OUTER JOIN 에서 데이터를 누락시키는가?  (0) 2023.09.13
mybatis associate, collection, alias  (0) 2023.09.12
Spring + MySQL + Mybatis  (0) 2023.08.17

### mysql 연동 후 dao/dto를 만들 클래스 구성

<br/>

### 쿼리 매퍼를 작성 (ex. UserMapper.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="kia.com.mybatistest.model.dao.UserMapper">
    <select id="getAllUserDataList" resultType="kia.com.mybatistest.model.dto.UserDto">
        select * FROM users
    </select>
</mapper>



- select * FROM {실제 데이터베이스 테이블 명}
- namespace : Mapper interface 위치
- select resultType : Mapping 될 dto 위치



### mybatis-config.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>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>



### application.yml에 mybatis 설정 추가

mybatis:
  config: mybatis-config.xml // config 위치 : static 바로 아래
  type-aliases-package: kia.com.mybatistest.model // dao,dto가 위치한 곳
  mapper-locations: mybatis/mapper/*.xml // mapper를 위한 xml 파일이 위치한 곳 ( static 아래가 아닌 resources 아래 )




### Mapper interface 작성

@Repository
@Mapper
public interface UserMapper {
    List<UserDto> getAllUserDataList();
}



### Dto 구성

@Getter
@Setter
public class UserDto {
    private Long user_id;
    private String user_name;
    private String user_email;
    private String user_password;
    private LocalDateTime create_at;
    private LocalDateTime modified_at;

    public UserDto() {

    }

    public UserDto(String user_name, String user_email, String user_password, LocalDateTime create_at, LocalDateTime modified_at) {
        this.user_name = user_name;
        this.user_email = user_email;
        this.user_password = user_password;
        this.create_at = create_at;
        this.modified_at = modified_at;
    }

    public UserDto of(String user_name, String user_email, String user_password, LocalDateTime create_at, LocalDateTime modified_at) {
        return new UserDto(user_name, user_email, user_password, create_at, modified_at);
    }
}




### Service interface 작성

public interface UserServiceInterface {

    public List<UserDto> getAllUserDataList();
}



### Service implement 작성

@Service
@RequiredArgsConstructor
public class UserService implements UserServiceInterface {

    private final UserMapper userMapper;

    @Override
    public List<UserDto> getAllUserDataList() {
        return userMapper.getAllUserDataList();
    }
}



### Test Controller 구성

@RequiredArgsConstructor
@RestController
public class MemberTestController {

    private final UserService userService;

    @GetMapping("/user/test")
    public List<UserDto> getAllDataList() {
        return userService.getAllUserDataList();
    }
}

 

 

* github : https://github.com/tjdwns4537/mybatis-practice

 

GitHub - tjdwns4537/mybatis-practice: 실습 및 테스트

실습 및 테스트. Contribute to tjdwns4537/mybatis-practice development by creating an account on GitHub.

github.com

 

+ Recent posts