Java 字符串的Jdbctemplate查询:EmptyResultDataAccessException:结果大小不正确:应为1,实际为0
我使用Jdbctemplate从数据库中检索单个字符串值。这是我的方法Java 字符串的Jdbctemplate查询:EmptyResultDataAccessException:结果大小不正确:应为1,实际为0,java,spring,jdbctemplate,Java,Spring,Jdbctemplate,我使用Jdbctemplate从数据库中检索单个字符串值。这是我的方法 public String test() { String cert=null; String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'"; cert = (
public String test() {
String cert=null;
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
cert = (String) jdbc.queryForObject(sql, String.class);
return cert;
}
在我的场景中,我的查询完全可能没有命中,所以我的问题是如何绕过以下错误消息
EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
在我看来,我应该返回null,而不是抛出异常。我怎样才能解决这个问题?提前谢谢。好的,我想好了。我只是把它包装在一个try-catch中,然后发回null
public String test() {
String cert=null;
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
try {
Object o = (String) jdbc.queryForObject(sql, String.class);
cert = (String) o;
} catch (EmptyResultDataAccessException e) {
e.printStackTrace();
}
return cert;
}
这不是一个好的解决方案,因为控制流依赖于异常。在您的解决方案中,获取异常是正常的,在日志中包含异常也是正常的
public String test() {
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
List<String> certs = jdbc.queryForList(sql, String.class);
if (certs.isEmpty()) {
return null;
} else {
return certs.get(0);
}
}
公共字符串测试(){
String sql=“从codb_owner.TR_LTM_SLS_RTN中选择ID_NMB_SRZ,其中ID_str_rt='999'和ID_NMB_SRZ='602300099999';
List certs=jdbc.queryForList(sql,String.class);
if(certs.isEmpty()){
返回null;
}否则{
返回证书。获取(0);
}
}
在JdbcTemplate中,queryForInt
,queryForLong
,queryForObject
所有这些方法都希望执行的查询将返回一行且仅返回一行。如果没有行或多行将导致不正确的结果sultsizedataaccessexception
。现在正确的方法不是捕获此异常或EmptyResultDataAccessException
,而是确保您使用的查询只返回一行。如果根本不可能,则使用query
方法
List<String> strLst = getJdbcTemplate().query(sql,new RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
});
if ( strLst.isEmpty() ){
return null;
}else if ( strLst.size() == 1 ) { // list contains exactly 1 element
return strLst.get(0);
}else{ // list contains more than 1 elements
//your wish, you can either throw the exception or return 1st element.
}
List strLst=getJdbcTemplate().query(sql,新的行映射器{
公共对象mapRow(ResultSet rs,int rowNum)引发SQLException{
返回rs.getString(1);
}
});
if(strLst.isEmpty()){
返回null;
}else如果(strLst.size()==1){//列表正好包含1个元素
返回strLst.get(0);
}else{//列表包含1个以上的元素
//根据您的意愿,您可以抛出异常或返回第一个元素。
}
您可以使用group函数,以便查询始终返回结果。
即
您也可以使用而不是。两者都一样简单,唯一的区别是你打电话
现在,您可以在方法中直接使用此映射器从查询映射Account
域对象(jt
是JdbcTemplate
实例)
很好,但这是一个模式,你可能会希望重复。因此,您可以创建一个通用工厂方法来为任务创建一个新的工厂
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
我希望这有助于说明您现在可以非常轻松地以一种强大的方式组合各个部分,从而使您的域更简单
更新2:与用于可选值的组合,而不是null
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
public静态结果文本提取器singleton可选提取器(
RowMapper实际上,您可以使用JdbcTemplate
并根据自己的喜好自定义方法。我的建议如下:
public String test() {
String cert = null;
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
ArrayList<String> certList = (ArrayList<String>) jdbc.query(
sql, new RowMapperResultSetExtractor(new UserMapper()));
cert = DataAccessUtils.singleResult(certList);
return cert;
}
公共字符串测试(){
字符串cert=null;
String sql=“从codb\u owner.TR\u LTM\u SLS\u RTN中选择ID\u NMB\u SRZ
其中id_str_rt='999'和id_NMB_SRZ='602300099999';
ArrayList certList=(ArrayList)jdbc.query(
sql,新的RowMapperResultSetExtractor(新的UserMapper());
cert=DataAccessUtils.singleResult(certList);
返回证书;
}
它与原始的jdbc.queryForObject
一样工作,但是没有在size==0
时抛出新的EmptyResultDataAccessException
,因为在没有数据时返回null是我在使用queryForObject时经常要做的事情,因此我发现扩展JdbcTemplate并向我添加一个queryforullableObject非常有用方法与下面类似
public class JdbcTemplateExtended extends JdbcTemplate {
public JdbcTemplateExtended(DataSource datasource){
super(datasource);
}
public <T> T queryForNullableObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = query(sql, rowMapper);
if (results == null || results.isEmpty()) {
return null;
}
else if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
}
else{
return results.iterator().next();
}
}
public <T> T queryForNullableObject(String sql, Class<T> requiredType) throws DataAccessException {
return queryForObject(sql, getSingleColumnRowMapper(requiredType));
}
}
我很想知道是否有人认为这是一个好主意?我以前处理过这个问题,并在春季论坛上发布过
我们收到的建议是使用一种类型的SQlQuery
@Component
public class FindID extends MappingSqlQuery<Long> {
@Autowired
public void setDataSource(DataSource dataSource) {
String sql = "Select id from address where id = ?";
super.setDataSource(dataSource);
super.declareParameter(new SqlParameter(Types.VARCHAR));
super.setSql(sql);
compile();
}
@Override
protected Long mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getLong(1);
}
性能不清楚,但它工作正常且整洁。因为getJdbcTemplate()。queryForMap要求最小大小为1,但当它返回null时,它显示EmptyResultDataAccesso fix dis何时可以使用下面的逻辑
Map<String, String> loginMap =null;
try{
loginMap = getJdbcTemplate().queryForMap(sql, new Object[] {CustomerLogInInfo.getCustLogInEmail()});
}
catch(EmptyResultDataAccessException ex){
System.out.println("Exception.......");
loginMap =null;
}
if(loginMap==null || loginMap.isEmpty()){
return null;
}
else{
return loginMap;
}
Map loginMap=null;
试一试{
loginMap=getJdbcTemplate().queryForMap(sql,新对象[]{CustomerLogInInfo.GetCustLoginMail()});
}
捕获(EmptyResultDataAccessException ex){
系统输出打印项次(“例外情况”);
loginMap=null;
}
if(loginMap==null | | loginMap.isEmpty()){
返回null;
}
否则{
返回登录映射;
}
在Postgres中,几乎任何单值查询都可以通过包装返回值或空值:
SELECT (SELECT <query>) AS value
选择(SELECT)作为值
因此避免了来电者的复杂性。对于拜伦,你可以试试这个
public String test(){
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
List<String> li = jdbcTemplate.queryForList(sql,String.class);
return li.get(0).toString();
}
公共字符串测试(){
String sql=“从codb\u owner.TR\u LTM\u SLS\u RTN中选择ID\u NMB\u SRZ
其中id_str_rt='999'和id_NMB_SRZ='602300099999';
List li=jdbcTemplate.queryForList(sql,String.class);
返回li.get(0.toString();
}
制作
jdbcTemplate.queryForList(sql, String.class)
工作时,请确保jdbcTemplate的类型为
org.springframework.jdbc.core.JdbcTemplate
我刚刚捕捉到这个“EmptyResultDataAccessException”
我们可以使用query代替queryForObject,query和queryForObject的主要区别在于查询返回对象的列表(基于行映射器返回类型)如果没有从数据库接收到数据,那么这个列表可能是空的,而queryForObject总是希望从db中只提取一个对象,既不是null,也不是多行,如果结果是空的,那么queryForObject抛出EmptyResultDataAccessException,我已经编写了一个使用查询的代码来克服EmptyResultDataAccess的问题如果结果为空,则出现异常
----------
public UserInfo getUserInfo(字符串用户名、字符串密码){
String sql=“选择firstname、lastname、ad
public class JdbcTemplateExtended extends JdbcTemplate {
public JdbcTemplateExtended(DataSource datasource){
super(datasource);
}
public <T> T queryForNullableObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = query(sql, rowMapper);
if (results == null || results.isEmpty()) {
return null;
}
else if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
}
else{
return results.iterator().next();
}
}
public <T> T queryForNullableObject(String sql, Class<T> requiredType) throws DataAccessException {
return queryForObject(sql, getSingleColumnRowMapper(requiredType));
}
}
String result = queryForNullableObject(queryString, String.class);
@Component
public class FindID extends MappingSqlQuery<Long> {
@Autowired
public void setDataSource(DataSource dataSource) {
String sql = "Select id from address where id = ?";
super.setDataSource(dataSource);
super.declareParameter(new SqlParameter(Types.VARCHAR));
super.setSql(sql);
compile();
}
@Override
protected Long mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getLong(1);
}
Long id = findID.findObject(id);
Map<String, String> loginMap =null;
try{
loginMap = getJdbcTemplate().queryForMap(sql, new Object[] {CustomerLogInInfo.getCustLogInEmail()});
}
catch(EmptyResultDataAccessException ex){
System.out.println("Exception.......");
loginMap =null;
}
if(loginMap==null || loginMap.isEmpty()){
return null;
}
else{
return loginMap;
}
SELECT (SELECT <query>) AS value
public String test(){
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
List<String> li = jdbcTemplate.queryForList(sql,String.class);
return li.get(0).toString();
}
jdbcTemplate.queryForList(sql, String.class)
org.springframework.jdbc.core.JdbcTemplate
public Myclass findOne(String id){
try {
Myclass m = this.jdbcTemplate.queryForObject(
"SELECT * FROM tb_t WHERE id = ?",
new Object[]{id},
new RowMapper<Myclass>() {
public Myclass mapRow(ResultSet rs, int rowNum) throws SQLException {
Myclass m = new Myclass();
m.setName(rs.getString("name"));
return m;
}
});
return m;
} catch (EmptyResultDataAccessException e) { // result.size() == 0;
return null;
}
}
if(m == null){
// insert operation.
}else{
// update operation.
}
----------
public UserInfo getUserInfo(String username, String password) {
String sql = "SELECT firstname, lastname,address,city FROM users WHERE id=? and pass=?";
List<UserInfo> userInfoList = jdbcTemplate.query(sql, new Object[] { username, password },
new RowMapper<UserInfo>() {
public UserInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
UserInfo user = new UserInfo();
user.setFirstName(rs.getString("firstname"));
user.setLastName(rs.getString("lastname"));
user.setAddress(rs.getString("address"));
user.setCity(rs.getString("city"));
return user;
}
});
if (userInfoList.isEmpty()) {
return null;
} else {
return userInfoList.get(0);
}
}
public Optional<String> test() {
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
return jdbc.queryForList(sql, String.class)
.stream().findFirst();
}
String cert = DataAccessUtils.singleResult(
jdbcTemplate.queryForList(
"select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN where ID_STR_RT = :id_str_rt and ID_NMB_SRZ = :id_nmb_srz",
new MapSqlParameterSource()
.addValue("id_str_rt", "999")
.addValue("id_nmb_srz", "60230009999999"),
String.class
)
)
if(jdbcTemplate.queryForMap("select * from table").size() > 0 ) /* resulted exception */
if(jdbcTemplate.queryForList("select * from table").size() > 0) /* no exception */