このシナリオをキャプチャするキーワードが不足しているため、ここで説明します。クラスは簡略化されています。POJO DTOのJPA同期/コミットエラーを保存したくなくても
この与えられた:例外がdiscountService.hasDiscountときにスローされる
public ItemController {
@Autowired
ItemDtoService ItemDtoService;
@Autowired
DiscountService discountService;
@RequestMapping(value = "/viewItems", method = RequestMethod.POST)
public void process() {
List<ItemDto> ItemDtos = ItemDtoService.getItemDtos();
for(ItemDto i: ItemDtos) {
boolean isDiscounted = discountService.hasDiscount(i); //throws exception here on iteration 2 and the last iteration, ItemDto was discounted
if (isDiscounted) {
i.setPrice(discountService.getDiscountedPrice(i));
//do some other i.setter, basically modify the pojo
}
}
}
}
を:後続の反復
- と前の反復、ItemDtoは、割引されました。
例外は次のとおりです。
Caused by: org.hibernate.exception.SQLGrammarException: could not update: [somepackage.ItemDto#364]
そしてどこかでスタックトレースにあなたがこれを表示されます。
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)"
問題はそのメソッドの呼び出しであることが@Transactionalで下にDAOのメソッドを使用しています(と多分それは唯一のクエリ、複雑なクエリですが、正当な理由のために)。 JPA Txマネージャがメソッドコール終了時にジョブを実行すると、pojoが変更されたものとみなされ、それを同期しようとします。 ItemDtoService.getItemDtos内にはgetEntityManager()。createNativeQuery(nativeSql、ItemDto.class)が使用されているため、ItemDto pojoには@Entityがあります。その他の5つのクラスの詳細は次のとおりです。
@Entity
public class ItemDto{
//body
}
@Service
public class ItemService {
@Autowired
ItemDao itemDao;
public List<ItemDto> getItems() {
return itemDao.getItems(); //for sake of simplicity
}
}
@Repository
@Transactional
public class ItemDaoImpl {
public List<ItemDto> getItems() {
String nativeSql = "select...."
return getEntityManager().createNativeQuery(nativeSql, ItemDto.class);
}
}
@Service
public class DiscountService {
@Autowired
DiscountDao discountDao;
public boolean hasDiscount(ItemDto i) {
boolean hasDiscount = discountDao.hasDiscount(i);
//do other service stuff that might influence the hasDiscount flag
return hasDiscount;
}
}
@Repository
@Transactional
public class DiscountDaoImpl {
public boolean hasDiscount(ItemDto i) {
String nativeSql = "select...."
boolean hasDiscount;
//in reality the query is a complicated joins, executes and returns if has discount or not
return hasDiscount;
}
}
私は間違っていますか?
私が試したと働いていたオプションの一部を以下に示します。
- は、彼らが唯一のクエリなので(負の効果はしかし、それらは あるかもしれないですDaoのメソッド 上(読み取り専用=真)@Transactionalに追加します故意による複雑なクエリへのトランザクション、及びダーティ・リード防止する ロックを必要とするかもしれない)コントローラで
- 、修飾のための別個のループを作成し、それは 次いで が割り引かれるアイテムとシーイングをループするための2つのループ、1を持っています、それらの情報をどこかに保存する言ったのPOJOの修正
を行う第二 ループ、上、後で参照する私は他のオプションを見て、あなたはそれがコード化された方法と間違って何かを見たらコメントしてくださいしています。私はちょうど見つけ