JDBCマッピング単一エンティティの概要

3855 ワード

シーン
jdbcメソッドqueryForObject()クエリを使用すると、結果が一致しない場合に例外が放出されます.次のように、ビジネス処理時に条件に基づいたクエリーに結果があるかどうかを判断する必要があります.
			//       
			AuthUserInfoEntity authUserInfoEntity = new AuthUserInfoEntity();
			authUserInfoEntity.setId(id);
			if (authUserInfoDao.exists(authUserInfoEntity)) {
				authUserInfoEntity = authUserInfoDao.findOne(id);
				AuthUserInfoDto authUserInfoDto = new AuthUserInfoDto();
				BeanUtils.copyProperties(authUserInfoDto, authUserInfoEntity);
				return new Response(status.value(), msg, authUserInfoDto);
			} else {
				status = HttpStatus.NO_CONTENT;
				msg = "       !";
			}

シナリオ1
JdbcTemplateを直接継承し、queryForObject()メソッドを書き換えるには、次のようにします.
package com.xakj.util;

import java.util.Collection;
import java.util.List;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.RowMapperResultSetExtractor;

public class IJdbcTemplate extends JdbcTemplate {
	/**
	 *   JdbcTemplate   queryForObject       requiredSingleResult,
	 *             null(       )
	 */
	@Override
	public  T queryForObject(String sql, Class requiredType)
			throws DataAccessException {

		return queryForObject(sql, getSingleColumnRowMapper(requiredType));
	}

	@Override
	public  T queryForObject(String sql, RowMapper rowMapper)
			throws DataAccessException {
		List results = query(sql, rowMapper);
		return requiredSingleResult(results);
	}
	
	@Override
	public  T queryForObject(String sql, RowMapper rowMapper, Object... args)
			throws DataAccessException {
		List results = query(sql, args, new RowMapperResultSetExtractor(rowMapper, 1));
		return requiredSingleResult(results);
	}
	
	public static  T requiredSingleResult(Collection results)
			throws IncorrectResultSizeDataAccessException {
		int size = (results != null ? results.size() : 0);
		if (size == 0) {
			return null;
		}
		if (results.size() > 1) {
			throw new IncorrectResultSizeDataAccessException(1, size);
		}
		return results.iterator().next();
	}
}


dao層クエリー時にIJdbcTemplateを直接呼び出し、
	@Autowired
    private IJdbcTemplate jdbcTemplate;

ビジネス・レイヤは、クエリーの結果が空であるかどうかを判断するだけです.
シナリオ2
書き換えではなく、daoのクエリー・メソッドを直接変更して、単一のオブジェクトの元のコードをクエリーします.
	/**
     *          
     */
    @Override
    public AuthUserInfoEntity findOne(String id) {
		StringBuffer sql = new StringBuffer();
		sql.append(" SELECT * ");
		sql.append(" FROM AUTH_USER_INFO WHERE 1=1 ");

		RowMapper rowMapper = new BeanPropertyRowMapper(AuthUserInfoEntity.class);
		return this.jdbcTemplate.queryForObject(sql.toString(), rowMapper, id);
	}

個々のオブジェクト最適化コードを問い合せるには、次の手順に従います.
    /**
	 *           
	 */
	@Override
	public AuthUserInfoEntity findOne(String id) {
		StringBuffer sql = new StringBuffer();
		List params = new ArrayList();

		sql.append(" SELECT * ");
		sql.append(" FROM AUTH_USER_INFO WHERE 1=1 ");
		params.add(id);

		List authUserInfoEntitys = this.jdbcTemplate.query(sql.toString(), 
			params.toArray(), new BeanPropertyRowMapper(AuthUserInfoEntity.class));
		//          null
		if(authUserInfoEntitys.size() == 0){
			return null;
		}else{
			return authUserInfoEntitys.get(0);
		}
	}

ビジネス層も空かどうかを判断する必要があります.
まとめ
明らかに第1の方法はもっと合理的で、第2の方法は使用を推奨しないで、コードは簡単であればあるほど良いです.しかし、JdbcTemplateの下位層では実質的にqueryForObject()メソッドがqueryメソッドを呼び出し、戻り時に最初の値を取得しただけです.