使用RowMapper和JdbcTemplate时出现了NullPointerException

4
我有两个实体——用户和访问组。当我使用JdbcTemplate中的RowMapper从MySQL数据库获取用户实体时,如果在UserRowMapper中不使用accessgroup的setter,则没有NullPointerException,但是AccessGroup accessGroup中会有null值。请看下面的表、实体和Dao代码。
表:
CREATE TABLE `users` ( `USER_ID` int(11) NOT NULL AUTO_INCREMENT, `USER_EMAIL` varchar(255) DEFAULT NULL, `USER_NAME` varchar(255) DEFAULT NULL, `USER_PWD` varchar(255) DEFAULT NULL, `ACCESSGROUP_GROUP_ID` int(11) DEFAULT NULL, PRIMARY KEY (`USER_ID`), KEY `FK_users_ACCESSGROUP_GROUP_ID` (`ACCESSGROUP_GROUP_ID`), CONSTRAINT `FK_users_ACCESSGROUP_GROUP_ID` FOREIGN KEY (`ACCESSGROUP_GROUP_ID`) REFERENCES `access_group` (`GROUP_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
CREATE TABLE `access_group` ( `GROUP_ID` int(11) NOT NULL AUTO_INCREMENT, `GROUP_NAME` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`GROUP_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
实体:
@Entity @Table(name = "users") public class User implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "USER_ID") private Integer userId; @Column(name = "USER_EMAIL") private String userEmail; @Column(name = "USER_NAME") private String userName; @Column(name = "USER_PWD") private String userPwd; @JoinColumn(name = "ACCESSGROUP_GROUP_ID", referencedColumnName = "GROUP_ID") @ManyToOne private AccessGroup accessGroup; }
@Entity @Table(name = "access_group") public class AccessGroup implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "GROUP_ID") private Integer groupId; @Basic(optional = false) @Column(name = "GROUP_NAME") private String groupName; @OneToMany(mappedBy = "accessGroup") private Set users;
}
Dao:
@Repository("userDao") public class UserDaoImpl implements IUserDao {
@Autowired private JdbcTemplate jdbcTemplate;
@Value("${sql.user.get.email.pwd}") private String getByEmailAndPwd;
//sql.user.get.email.pwd=SELECT * FROM users WHERE user_email = ? AND user_pwd = ?
@Transactional @Override public User getUserByEmailAndPwd(String email, String password) { return jdbcTemplate.queryForObject(getByEmailAndPwd, new Object[]{email, password}, new UserRowMapper()); } }
    @Repository("accessGroupDao")
    public class AccessGroupDaoImpl implements IAccessGroupDao {
    
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        @Value("${sql.accessgroup.get.id}")
        private String getAccessGroupById;
      //sql.accessgroup.get.id=SELECT * FROM access_group WHERE GROUP_ID = ?
    
        @Transactional
        @Override
        public AccessGroup getGroupById(int id) {
            return jdbcTemplate.queryForObject(getAccessGroupById, new Object[]{id}, new AccessGroupRowMapper());
        }

RowMappers

    @Component
    public class UserRowMapper implements RowMapper {
    
        private AccessGroupService accessGroupService;
    
        @Autowired
        public void setAccessGroupService(AccessGroupService accessGroupService) {
            this.accessGroupService = accessGroupService;
        }
    
        @Override
        public User mapRow(ResultSet resultSet, int i) throws SQLException {
            User user = new User();
            user.setId(resultSet.getInt("USER_ID"));
            user.setEmail(resultSet.getString("USER_EMAIL"));
            user.setName(resultSet.getString("USER_NAME"));
            user.setpwd(resultSet.getString("USER_PWD"));
            //在此添加user.setAccessGroup(accessGroupService.getGroupById(resultSet.getInt("ACCESSGROUP_GROUP_ID")))会导致NPE异常。
            return user;
        }

    public class AccessGroupRowMapper implements RowMapper {
    
        @Override
        public AccessGroup mapRow(ResultSet resultSet, int i) throws SQLException {
            AccessGroup accessGroup = new AccessGroup();
            accessGroup.setId(resultSet.getInt("GROUP_ID"));
            accessGroup.setName(resultSet.getString("GROUP_NAME"));
            return accessGroup;
        }
    }


让我们从这个问题开始:你知道 AccessGroupService accessGroupService 是否被正确注入了吗?你能够“检查” resultSet.getInt("ACCESSGROUP_GROUP_ID") 吗? - x80486
1
显然它会是 null……你正在自己创建一个实例,却期望 Spring 把某些东西注入进去。不由 Spring 管理的 bean 实例将不会被注入。你为什么标注了 JPA 注解但又使用 JDBC? - M. Deinum
1
如果您能指出具体是在哪里出了问题,那将更有帮助。您已经有了日志,可能知道它在哪一行出了问题。 - Yogesh Sharma
1个回答

0

1)在您的@Entity类“User”中添加以下属性,并生成getter和setter方法:

@Transient
private Integer userIdTransientField; 

@Transient 表示该属性不会被存储在数据库中

2)修改 RowMapper 类:

将此行替换为以下内容:

user.setId(resultSet.getInt("USER_ID")); -> user.setUserIdTransientField(resultSet.getInt("USER_ID"));

3) 当您引用“用户”对象并且想要对jdbcTemplate进行更新/删除或者仅仅想要获取Id值时,请使用getUserIdTransientField方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接