今日偶然発見された隠れたバグを記録する
具体的には、Student id = 1などのレコードをクエリし、nameなどのstudentオブジェクトの属性を変更してから、updateステートメントを実行してjpaを介してフィールド年齢を変更します。例:update student set年齢= 1、ここでid = 1。最後に、データベースの経過時間の更新に加えて、名前フィールドも更新され、updateコマンドが2つの更新を実行したことがわかりました。テストコードは次のとおりです
サービス
@Service
@Transactional(readOnly = true)
public class LabelConfigService {
private ISysLabelConfigRepository iSysLabelConfigRepository;
@Autowired
public LabelConfigService(ISysLabelConfigRepository iSysLabelConfigRepository){
this.iSysLabelConfigRepository = iSysLabelConfigRepository;
}
@Transactional
public void testUpdate() {
SysLabelConfig labelConfig = iSysLabelConfigRepository.findOne(2637);
labelConfig.setRemark("wlllllllllllll");
//即使不执行下面的update labelConfig依然会update
iSysLabelConfigRepository.updateSource(labelConfig.getId(),12);
}
}
リポジトリ
public interface ISysLabelConfigRepository extends JpaRepository<SysLabelConfig,Integer>
,JpaSpecificationExecutor<SysLabelConfig> {
@Modifying
@Query("update SysLabelConfig set source=?2 where id=?1")
void updateSource(Integer id, Integer source);
}
テスト
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ApplicationBootstrap.class)
@WebAppConfiguration
public class TestSysLabelConfig {
@Autowired
private LabelConfigService labelConfigService;
@Test
public void testUpdate(){
labelConfigService.testUpdate();
}
}
次のようにSQLを実行します
0:24:16.495 [main] INFO c.c.j.m.s.s.TestSysLabelConfig - Started TestSysLabelConfig in 23.558 seconds (JVM running for 25.682)
Hibernate: select syslabelco0_.id as id1_17_0_, syslabelco0_.create_time as create_t2_17_0_, syslabelco0_.creator as creator3_17_0_, syslabelco0_.label_category as label_ca4_17_0_, syslabelco0_.label_name as label_na5_17_0_, syslabelco0_.label_sub_category as label_su6_17_0_, syslabelco0_.remark as remark7_17_0_, syslabelco0_.source as source8_17_0_ from sys_label_config syslabelco0_ where syslabelco0_.id=?
Hibernate: update sys_label_config set label_category=?, label_name=?, label_sub_category=?, remark=?, source=? where id=?
Hibernate: update sys_label_config set source=? where id=?
実際、updateステートメントが実行されなくても、変更されたデータベースエンティティオブジェクトは自動的に更新されます。!!
解決
1.物の下にあるエンティティオブジェクトのプロパティを変更しないでください
2.リポジトリのインターフェースメソッドに物事を置きます
ps:エンティティオブジェクトの操作に注意してください。エンティティオブジェクトの属性を変更したり、エンティティオブジェクトをvoオブジェクトに変換してから、さらに操作を実行したりしないことをお勧めします。