SpringFramework/BASIC

[MyBatis] resultMap / #{ } 문법 바인딩변수 처리

유혁스쿨 2020. 9. 3. 19:50
728x90
반응형

resultMap #{ } 문법

 

[resultMap] 

MyBatis에서는 SqlSessionTemplate를 사용하거나 MapperInterface를 사용할때 모두 resultMap이라는 기능을 사용할 수 있습니다.

 

먼저, 우리가 목록을 조회하거나 하나의 특정 행의 정보를 얻어DB로부터 얻어오고자 할 때,

DB에 접근해서 해당 컬럼의 값을 가져와 VO객체의 getter()메서드를 통해 객체에 저장해주는 작업을 해주며, 이때에 타입까지 맞게 변환시켜주는 작업을 해야합니다

 

SqlSessionTemplate에서는 이 작업을 RowMapper라는 인터페이스로 대신 처리 해줬습니다.

class BoardMapper implements RowMapper<DataVO>{

	@Override
	public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		BoardVO b = new BoardVO();
		b.setBoardNo(rs.getInt("board_no"));
		b.setWriter(rs.getString("writer"));
		b.setTitle(rs.getString("title"));
		b.setContent(rs.getString("content"));
		return b;
	}
		
}

MyBatis에서는 RowMaper와 같은 처리를 해주는 기능인 resultMap resultType이 있습니다

이번 포스팅에서는 resultMap에 대해서 정리하겠습니다.

 

 

resultMap은 컬럼명과 VO객체의 클래스 필드명이 서로 일치하지 않을때 , 참조할수 있는 기준이 없기때문에 자동으로
RowMapper처리를 해줄수 없습니다.

 

 

그러므로 <resultMap>이라는 태그를 사용하여서 컬럼명과 VO 필드명을 각각 기입해주는 작업을 미리 등록해놓습니다. <resultMap> 속성에는 id속성과 type 속성이 있습니다

id속성에는 쿼리문에서 참조할수 있는 Map이름을 작성해주시고 type속성에는 참조할 VO클래스의 패키지 경로+클래스명을 선언해 줍니다. 

 

이 작업을 미리 선언했을때 복수개의 목록을 가져오거나 한 행의 정보를 얻오는 쿼리문을 작성하는 <select>태그의 resultMap이라는 속성에 아까 선언해줬던 <resultMap> id속성을 지정해주면 쿼리문이 작동한 후 얻어온 정보들을 반환하게되는데 <resultMap>에서 선언했던 기준으로 RowMapper와 같이 처리를 해주며 반환 또한 선언했던 type으로 반환 해줍니다.

 

 


[예시코드]

public Interface IDataDAO {
    
    public List<DataVO> getList(DataVO d);

    public DataVO getData(int dNo);
    
}
@Repository
public class DataDAO implements IDataDAO {
	
    @Autowired 
    private SqlSession sqlSession;

    
    @Override
    public List<DataVO> SelectListD(DataVO d) {
        return this.sqlSession.selectList("Data.d_list",d);
    }

    @Override
    public DataVO selectOneD(int dNo) {
        return this.sqlSession.selectOne("d_Info",dNo);
    }
}
public class DataVO{
	private int dNo;
    private String dId;
    private String dName;
}
<?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="Data">

    <resultMap type="com.spring.database.mybatis.score.model.DataVO" id="DataMap">
        <id property="dataNo" column="data_no"/> 
        <result property="dataId" column="data_id"/>
        <result property="dataName" column="data_name"/>
    </resultMap>
    
    <select id="d_list" resultMap="DataMap">
        select * from Data order by dno desc 
    </select>
		
    <select id="d_info" resultType="DataMap">
        select * from Data where dno=#{dno}
    </select>

</mapper>

 

 

 

JDBC템플릿이었다면 rowMapper클래스를 만들어서 어떤 setter에 어떻게 getint getString 를 해서 넣을것인가를 만들었습니다.

class DaterMapper implements RowMapper<DataVO>{

	@Override
	public DataVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		DataVO data = new DataVO();
		data.setDataNo(rs.getInt("data_no"));
		data.setDataId(rs.getString("data_id"));
		data.setDataName(rs.getString("data_name"));
		return data;
	}
}

RowMapper와 같이 resultMap도 미리 하나를 만들어 놓고 사용합니다.

    <resultMap type="com.spring.database.mybatis.score.model.DataVO" id="DataMap">
        <id property="dataNo" column="data_no"/> 
        <result property="dataId" column="data_id"/>
        <result property="dataName" column="data_name"/>
    </resultMap>

둘이 굉장히 닮았죠?

resultMap은 RowMapper에서 했던 객체에 DB컬럼을 넣는 것과 같은 처리를 하고있는것입니다. 
알아서 타입까지 맞춰 저장해줍니다

 

이렇게 선언해둔 resultMap의 id를 쿼리의태그 resultMap속성에 넣어주면 
List를 리턴할때는 객체에 저장하고 그 객체들을 List에넣어주는데 이러한 반복 작업을 끝낸 후 List를 반환하며,
객체를 리턴할때는 자동으로 객체에 담아 넣은후 객체를 반환해 줍니다.

 

resultMap은 DB컬럼명과 필드명이 일치하지 않을때 선언해줍니다. 
관례상 sql은 띄어쓰기를 언더바로 처리하지만 자바는 카멜케이스로 처리합니다(띄어쓰기를 하지않고 대문자)

 

 

세팅이 된 것을 사용할때는 <select>태그 속성의 resultMap이라는 속성으로 <resultMap> id속성을 참조합니다. 

    <resultMap type="com.spring.database.mybatis.score.model.DataVO" id="DataMap">
        <id property="dataNo" column="data_no"/> 
        <result property="dataId" column="data_id"/>
        <result property="dataName" column="data_name"/>
    </resultMap>
    
    <select id="d_list" resultMap="DataMap">
        select * from Data order by dno desc 
    </select>
		
    <select id="d_info" resultMap="DataMap">
        select * from Data where dno=#{dno}
    </select>

<select>태그에서 resultMap속성에 <resultMap> id속성값을 기준으로 참조하는 예제코드

 


#{ }

 

#{ } 문법은 기본적으로 전통적인 JDBC방식의 혹은  Jdbc-Template가 사용하는 PreparedStatement의 바인딩 변수 처리를 대신 해줍니다.

 

 

PremaredStatement는 바인딩변수를 사용하여 쿼리문에 작성해야할 참조할 값들을 ?로 대신해주고

public void insertD(DataVO data) {
    try {
        con=DriverManager.getConnection(url, user, pwd);
        sql="insert into Data values(data_no_seq.nextval,?,?,?,sysdate)";
        pstmt=con.prepareStatement(sql);
        pstmt.setInt(1, eg.getdata_no());
        pstmt.setString(2, eg.getdata_id());
        pstmt.setString(3, eg.getdata_name());
        pstmt.executeUpdate();
    }catch(Exception e) {
        e.printStackTrace();
    }finally {
        try {
            if(pstmt!=null) pstmt.close();
            if(con!=null) con.close();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
}

각 ?에 맞게 객체에 접근하여 getter메서드로 값을 받아오거나 넘겨받은 인자값을 PreparedStatement의 set타입() 메서드로 바인딩 ?기호의 각 순서에 맞게 값을 넣어줬습니다.RowMapper도 똑같았죠

 

 

하지만 #{ }문법을 사용한다면

<insert>
    insert into Data values(data_no_seq.nextval,#{dataNo},#{dataId},#{dataName},sysdate)
</insert>

이렇게 간략하게 처리가되는데

이때 만약 매서드의 매개변수가 객체라면 해당 객체의 필드명을 작성해주시면 됩니다. 

필드명을 쓰지만 아마 이때도 EL이나 컨테이너 빈 등록의 property속성 주입 처럼 setter메서드가 작동하게 되지 않나 추측해봅니다.

 

또 where조건식에 들어가게되는 매개변수가 객체가 아닌 String 혹은 기본타입일 경우에는 #{ } 안에 변수명을 써주면 됩니다.

 

 

728x90
반응형