본문 바로가기
spring/토비의 스프링

토비의 스프링 Vol. 1 정리 - 3장 템플릿 - 3

by Empering 2020. 4. 19.
반응형

토비의 스프링 Vol.1 정리 - 3 - 3

3장 템플릿


스프링의 JdbcTemplate

스프링은 JDBC를 이용하는  DAO에서 사용할 수 있도록 준비된 다양한 템플릿과 콜백을 제공한다.

 

지금까지 만들었던 UserDao는 DataSource를 DI 받아서 JdbcContext에 주입해 템플릿 오브젝트로 만들어 사용한다. JdbcContext를 JdbcTemplate로 변경해 적용해본다. 단순히 기존에 JdbcContext setter 메소드를 JdbcTemplate로 변경하면 된다.

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

 

JdbcTemplate 적용

1. update()

템플릿으로 부터 Connection을 받고 PreparedStatementCreator 타입의 콜백을 되돌려 받아 사용하는 JdbcTemplate 템플릿 메소드

 

    public void deleteAll() throws SQLException {
        // PreparedStatementCreator 타입 콜백을 정의해 사용하는 경우
        this.jdbcTemplate.update(connection -> {
            return connection.prepareStatement("DELETE FROM USERS");
        });

        // 내장콜백을 사용하는 경우
        this.jdbcTemplate.update("DELETE FROM USERS");
    }
    
    public void add(final User user) throws SQLException {
    	// 바인딩할 파라미터가 있는 경우
        this.jdbcTemplate.update("INSERT INTO USERS(id, name, password) VALUES(?, ?, ?)",
        	user.getId(), user.getName(), user.getPassword());
    }

 

 

2. query()

update()와 동일한 첫번째 콜백과 두번째 파라미터로 ResultSet을 받고 ResultSetExtractor 타입의 콜백을 되돌려 받아 사용하는 JdbcTemplate 템플릿 메소드

    public int getCount() throws SQLException {
        return this.jdbcTemplate.query(connection -> {
            return connection.prepareStatement("SELECT COUNT(*) FROM USERS");
        }, resultSet -> {
            resultSet.next();
            return resultSet.getInt(1);
        });
    }

 

물론 위처럼 하지않고 query() 로 오버로딩된 메소드중 적절한 것을 사용하면된다.

    @Nullable
    public <T> T query(PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        this.logger.debug("Executing prepared SQL query");
        return this.execute(psc, new PreparedStatementCallback<T>() {
            @Nullable
            public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
                ResultSet rs = null;

                Object var3;
                try {
                    if (pss != null) {
                        pss.setValues(ps);
                    }

                    rs = ps.executeQuery();
                    var3 = rse.extractData(rs);
                } finally {
                    JdbcUtils.closeResultSet(rs);
                    if (pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }

                return var3;
            }
        });
    }

    @Nullable
    public <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query((PreparedStatementCreator)psc, (PreparedStatementSetter)null, (ResultSetExtractor)rse);
    }

    @Nullable
    public <T> T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementSetter)pss, (ResultSetExtractor)rse);
    }

    @Nullable
    public <T> T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query(sql, this.newArgTypePreparedStatementSetter(args, argTypes), rse);
    }

    @Nullable
    public <T> T query(String sql, @Nullable Object[] args, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
    }

    @Nullable
    public <T> T query(String sql, ResultSetExtractor<T> rse, @Nullable Object... args) throws DataAccessException {
        return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
    }

    public void query(PreparedStatementCreator psc, RowCallbackHandler rch) throws DataAccessException {
        this.query((PreparedStatementCreator)psc, (ResultSetExtractor)(new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)));
    }

    public void query(String sql, @Nullable PreparedStatementSetter pss, RowCallbackHandler rch) throws DataAccessException {
        this.query((String)sql, (PreparedStatementSetter)pss, (ResultSetExtractor)(new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)));
    }

    public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch) throws DataAccessException {
        this.query(sql, this.newArgTypePreparedStatementSetter(args, argTypes), rch);
    }

    public void query(String sql, Object[] args, RowCallbackHandler rch) throws DataAccessException {
        this.query(sql, this.newArgPreparedStatementSetter(args), rch);
    }

    public void query(String sql, RowCallbackHandler rch, @Nullable Object... args) throws DataAccessException {
        this.query(sql, this.newArgPreparedStatementSetter(args), rch);
    }

 

 

3. queryForInt(), queryForLong(), queryForMap(), queryForList()

query()에서 ResultSetExtractor 타입의 콜백에 해당 타입 결과를 되돌려 받아 사용할 수 있는 JdbcTemplate 템플릿 메소드 (Spring 3.2.2 버전 이후부터는 queryForInt, queryForLong은 deprecated 됨)

 

    public int getCount() throws SQLException {
        // spring 3.2.2 버전 이후부터는 queryForInt 메소드가 deprecated 됨
        return this.jdbcTemplate.queryForInt("SELECT COUNT(*) FROM USERS");
    }

 

 

4. queryForObject()

query()에서 사용한 ResultSetExtractor 대신 RowMapper 콜백으로 사용해 결과로 ResultSet을 반환하는 메소드

queryForObject()는 SQL 실행 후 1개의 결과를 얻을 것을 기대하고 동작한다. 콜백의 ResultSet은 SQL 결과의 첫 행의 결과를 가리킨다.

 

    public User get(String userId) throws SQLException {
        return this.jdbcTemplate.queryForObject("SELECT * FROM USERS WHERE ID = ?",
                new Object[]{userId},
                (resultSet, rowNum) -> {
                    User user = new User();
                    user.setId(resultSet.getString("ID"));
                    user.setName(resultSet.getString("NAME"));
                    user.setPassword(resultSet.getString("PASSWORD"));
                    return user;
                });
    }

 

 

 

 

반응형

댓글