mybatis, ibatis selectKey 이슈 해결

Lee Seung Jae·2021년 5월 11일
1

SelectKey

xml에서 insert기능을 수행하려고 할때 auto_increment가 적용된 칼럼 값을 가져오고 싶을 때 많이 쓰는 selectKey이다.
이 selectKey를 사용하려면 다음과 같이 진행하면 된다.

repository클래스에서 해당 insert 기능을 수행하는 메소드에서 반환 값을 int 로 하여 구문은 실행함과 동시에 selectKey값을 int 변수에 담아준다.

<insert id="DAO.insert" parameterClass="java.util.HashMap">
  <selectKey keyProperty="DM_NO" resultClass="int">
    SELECT NVL(MAX(t.번호), 1) FROM TEST t
  </selectKey>
  INSERT INTO TEST("번호", "제목", "내용", "ID")
  VALUES ((SELECT NVL(MAX(t."번호") + 1, 1) FROM TEST t), #제목#, #내용#, #ID#)
  
</insert>

기본으로 auto increment속성은 안넣고 쿼리 자체에서 auto_increment 하게끔 쿼리를 생성했다.

여기서 문제가 발생했다. 상단의 selectKey가 Insert위에 또는 아래에 위치를 시켜도 항상 Insert문보다 앞에서 실행이 되기 때문에 처음 기본이 null이라면 1을 할당하는 번호 1번에서는 문제 없이 생성이 되지만 그 후에 insert가 2번이 되었을때는 2번이 되기전에 select구문이 한번 실행되기 때문에 여기서 번호가 차이가 나게 된다.

참고로 NVL()은 oracle db에서 제공되는 NULL처리 문법이다.
SQL별로 상이할 수 있는 점은 감안하자. 😭(ex: mysql-> IFNULL() ... )

여기서 검색을 해본 결과 MyBatis에서는 select Key 옵션에 order속성이 있는데 iBatis에는 type속성이 있다.
order="BEFORE" 또는 order="AFTER"로 MyBatis는 insert문이 실행되기 전 또는 후에 실행을 시킬 수 있다.

iBatis의 경우는 type="pre" 또는 type="post"가 있어서 마찬가지로 insert문 전,후로 실행되게끔 옵션을 줄 수 있다.

다시 오류 구문으로 가서 수정을 하자면

<insert id="DAO.insert" parameterClass="java.util.HashMap">
  INSERT INTO TEST("번호", "제목", "내용", "ID")
  VALUES ((SELECT NVL(MAX(t."번호") + 1, 1) FROM TEST t), #제목#, #내용#, #ID#)
  <selectKey keyProperty="DM_NO" resultClass="int" type="post">
    SELECT NVL(MAX(t.번호), 1) FROM TEST t
  </selectKey>
</insert>

이렇게 수정을 진행했다.
아까 오류가 났던 점을 해결했고 정상적으로 insert했을때의 번호와 selectKey로 조회한 번호가 같은값이 되었다.

@Repository
public class DAO extends EgovAbstractDAO {
  public int insertEx(HashMap<String, Object> ex){
    return (int) insert("diagramDAO.insertDiagram", ex);
  }
}

이렇게 된 selectKey를 자바에서 이런방식으로 return을 진행하여 Service 클래스에서

int abc = DAO.insertEx(HashMap<String, Object>);

이렇게 할당하여 int형 변수를 사용하면 되겠다.

21.05.12 수정 (코드리뷰 받으면서...)

코드리뷰를 하면서 이렇게 바로 Map의 key에 바로 value를 포함시켜주는 방법을 알게되었다.

@Repository
public class DAO extends EgovAbstractDAO {
  public void insertEx(HashMap<String, Object> ex){
    insert("diagramDAO.insertDiagram", ex);
  }
}

이렇게 해준뒤에 DB내에 xml에서 keyProperty로 값을준 칼럼이 있다면 Map을 사용하여 바로 키에 설정하여 사용할 수도 있다.

@Service
public class Service{
	@Autowired
    private DAO dao;

    public void insertDB(HashMap<String, Object> ex){
        dao.insertEx(ex);
        //이 아래에서 ex를 다시 호출해서 사용할 시...
    }
}

위의 코드에서 주석부분 아래로 ex라는 HashMap을 사용한다면 ex.get("DM_NO")를 하게되면 selectKey값이 들어가게 된다.

상황에 맞게 사용을 하면 될 것 같다.

profile
💻 많이 짜보고 많이 경험해보자 https://lsj8367.tistory.com/ 블로그 주소 옮김

0개의 댓글