【问题标题】:NamedParameterJdbcTemplate usage from inside its own Mapper [duplicate]NamedParameterJdbcTemplate 从它自己的 Mapper 内部使用 [重复]
【发布时间】:2016-03-05 18:54:59
【问题描述】:

我对 Spring 有点陌生,我正在使用 spring mvc 编写一个连接到 mysql db 的简单网页,但我得到空指针,我尝试在另一个 NamedParameterJdbcTemplate 当前正在执行的地方使用 NamedParameterJdbcTemplate 查询

通过此 bean 配置 (spring-web-servlet.xml) 进行的 db 定义

<bean id="dataSource" destroy-method="close"
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
        value="jdbc:mysql://#{systemEnvironment[OPENSHIFT_MYSQL_DB_HOST]}:#{systemEnvironment[OPENSHIFT_MYSQL_DB_PORT]}/#{systemEnvironment[OPENSHIFT_APP_NAME]}" />
    <property name="username"
        value="#{systemEnvironment[OPENSHIFT_MYSQL_DB_USERNAME]}" />
    <property name="password"
        value="#{systemEnvironment[OPENSHIFT_MYSQL_DB_PASSWORD]}" />
    <property name="initialSize" value="3" />
</bean>

还有这个配置类(SpringDBConfig.java)

@Configuration
public class SpringDBConfig {
    @Autowired
    DataSource dataSource;

    @Bean
    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

首先我的数据库就是这样的

CREATE TABLE `TIPOSREGALO` (
  `TIPOREGALO_ID` varchar(50) NOT NULL,
  `DESCRIPCION` varchar(5000) NOT NULL,
  `URLFOTO` varchar(255) NOT NULL, 
  PRIMARY KEY (`TIPOREGALO_ID`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `REGALOS` (
  `REGALO_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `TIPOREGALO_ID` varchar(50) NOT NULL,
  `TITULO` varchar(50) NOT NULL,
  `DESCRIPCION` varchar(5000) NOT NULL,
  `URLFOTO` varchar(255) NOT NULL, 
  `PRECIO` integer unsigned NOT NULL,
  PRIMARY KEY (`REGALO_ID`) USING BTREE,
  FOREIGN KEY (`TIPOREGALO_ID`) REFERENCES `TIPOSREGALO`(`TIPOREGALO_ID`) 
) ENGINE=INNODB DEFAULT CHARSET=utf8;

我的 DAO 像这样从控制器调用

@RequestMapping(value = "/gift/{id}", method = RequestMethod.GET)
public String giftdetail(@PathVariable("id") int regalo_id, Model model) {
    model.addAttribute("regalo", regaloService.findById(regalo_id));
    return "weddinglist/gift";
}

那个RegaloService方法是

@Override
public Regalo findById(int id) {
    return regaloDao.findById(id);
}

而regaloDao是

 @Repository
    public class RegaloDaoImpl implements RegaloDao {

        private final Logger logger = LoggerFactory.getLogger(RegaloDaoImpl.class);

        NamedParameterJdbcTemplate namedParameterJdbcTemplate;

        @Autowired
        public void setNamedParameterJdbcTemplate(
                NamedParameterJdbcTemplate namedParameterJdbcTemplate)
                throws DataAccessException {
            this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
        }

        @Override
        public Regalo findById(Integer regalo_id) {
            logger.debug("findById() id: \"{}\"", regalo_id);

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("regalo_id", regalo_id);

            String sql = "SELECT * FROM REGALOS WHERE REGALO_ID=:regalo_id";

            Regalo result = null;
            try {
                result = namedParameterJdbcTemplate.queryForObject(sql, params,
                        new RegaloMapper());
            } catch (EmptyResultDataAccessException e) {
                // do nothing, return null
            }
            return result;
        }
    ...

        private static final class RegaloMapper implements RowMapper<Regalo> {

            private final Logger logger = LoggerFactory
                .getLogger(RegaloMapper.class);

            public Regalo mapRow(ResultSet rs, int rowNum) throws SQLException {


                Regalo regalo = new Regalo();
                regalo.setRegalo_id(rs.getInt("REGALO_ID"));

                TipoRegaloDao tipoRegaloDao = new TipoRegaloDaoImpl();
                regalo.setTiporegalo(tipoRegaloDao.findById(rs
                        .getString("TIPOREGALO_ID")));

                regalo.setTitulo(rs.getString("TITULO"));
                regalo.setDescripcion(rs.getString("DESCRIPCION"));
                regalo.setUrlfoto(rs.getString("URLFOTO"));
                regalo.setPrecio(rs.getInt("PRECIO"));
                return regalo;
            }
        }
    }

如您所见,调用 regalo.setTiporegalo(tipoRegaloDao.findById(rs.getString("TIPOREGALO_ID")));当之前对 queryForObject 的调用没有完成时,在 Mapper 内部进行,然后执行到 TipoRegaloDaoImpl.findById() 并尝试调用一个空的 namedParameterJdbcTemplate 对象

@Repository
public class TipoRegaloDaoImpl implements TipoRegaloDao {

    private final Logger logger = LoggerFactory
            .getLogger(TipoRegaloDaoImpl.class);

    NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Autowired
    public void setNamedParameterJdbcTemplate(
            NamedParameterJdbcTemplate namedParameterJdbcTemplate)
            throws DataAccessException {
        logger.debug("setNamedParameterJdbcTemplate() namedParameterJdbcTemplate: \"{}\"", namedParameterJdbcTemplate);
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }

    @Override
    public TipoRegalo findById(String tiporegalo_id) {
        logger.debug("findById() id: \"{}\"", tiporegalo_id);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("tiporegalo_id", tiporegalo_id);

        String sql = "SELECT * FROM TIPOSREGALO WHERE TIPOREGALO_ID=:tiporegalo_id";

        TipoRegalo result = null;
        try {
            result = namedParameterJdbcTemplate.queryForObject(sql, params,
                        new TipoRegaloMapper());

            logger.debug("findById() result: \"{}\"", result);


        } catch (EmptyResultDataAccessException e) {
            logger.error("findById() Resultado vacio, excepcion " + e);
            // do nothing, return null
        } catch (Exception e) {
            logger.error("findById() No se que ha pasado aqui, excepcion " + e);
            // do nothing, return null
        }
        return result;
    }
 ....

并且 queryForObject 因空指针异常而失败

有什么线索吗?

谢谢

【问题讨论】:

    标签: java mysql spring spring-mvc


    【解决方案1】:
    TipoRegaloDao tipoRegaloDao = new TipoRegaloDaoImpl();
    

    这会创建一个 TipoRegaloDaoImpl,并且永远不会初始化它的 namedParameterJdbcTemplate。 Spring 只能自动装配它自己创建的 bean。不是您使用new 自己创建的。在 RegaloDaoImpl 中注入 TipoRegaloDao(并使映射器成为内部类而不是嵌套的静态类以使其访问该字段)。

    如果你使用构造函数注入而不是字段注入,你永远不会遇到这个问题,因为很明显 TipoRegaloDaoImpl 需要一个 namedParameterJdbcTemplate:它将是它的构造函数参数之一。但一般来说,每次使用new创建Spring bean,都会有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-15
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 2017-09-02
      相关资源
      最近更新 更多