在使用 MyBatis/Spring 框架進行數據持久化時,常見現象:數據已成功寫入數據庫,但隨即拋出 java.lang.NullPointerException,堆疊指向 DAO 的 insertVideoResource 方法。這通常是因為誤用 selectOne 執行插入操作,導致返回值處理錯誤。
public int insertVideoResource(VideoResource vr) {
// 錯誤:使用 selectOne 執行 INSERT 語句
return getSqlSession().selectOne(Advertising.class.getName() + ".insertVideoResource", vr);
}
selectOne 專為 查詢單條記錄 設計,期望返回結果對象(如 ID、實體)。useGeneratedKeys/keyProperty 獲取自增 ID),MyBatis 執行 selectOne 時獲取到 null。int id = dao.insert(...); id.toString()),觸發 NPE。insert 方法(推薦)public int insertVideoResource(VideoResource vr) {
// 返回影響行數(通常為 1)
return getSqlSession().insert(Advertising.class.getName() + ".insertVideoResource", vr);
}
<insert id="insertVideoResource" parameterType="VideoResource" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
INSERT INTO video_resource (aid, video_url) VALUES (#{aid}, #{videoUrl})
</insert>
Java 代碼仍用 insert(),插入後 vr.getId() 即可獲取生成的主鍵。
selectOne(如調用存儲過程返回值)public Integer insertVideoResource(VideoResource vr) { // 返回 Integer 而非 int
Object result = getSqlSession().selectOne(...);
return result != null ? (Integer) result : 0; // 空值保護
}
public int addVideoResource(Advertising ad) {
if (ad == null) return 0;
advertisingDao.insert(ad); // 假設此處已生成 ad.id
VideoResource vr = new VideoResource();
vr.setAid(ad.getId());
vr.setVideoUrl(ad.getVideoUrl());
return advertisingDao.insertVideoResource(vr); // 現在返回影響行數
}
insert 語句的 id 是否與 DAO 調用一致。log4j.logger.org.apache.ibatis=DEBUG)查看實際執行的 SQL 及返回值。