JPA的事务方法在已保存后更新列。

huangapple go评论155阅读模式
英文:

JPA Transactional method updates the column after already saving it

问题

我正在保存通过 REST Webservice POST 的一个对象,但在此之前我尝试更新一些字段。我有一个类 A,它有一个 B 作为其属性(没有关系,只是一个字段 - 复杂性由于该字段是一个单独的 JSON 字段/对象)。我试图在持久化 A 之前更新 B 的属性,这实际上运行得很好... 除了在插入新类之后,它还会更新该字段。类似这样的情况:

  1. public class A {
  2. @GeneratedValue(strategy = GenerationType.IDENTITY)
  3. @Id
  4. Long id;
  5. @Lob
  6. @Convert(converter = BConverter.class)
  7. B b_field;
  8. }
  9. public class B {
  10. List<String> someVals;
  11. List<Map<String, String>> amts;
  12. }
  13. @Converter
  14. public class BConverter implements AttributeConverter<B, String> {
  15. private final static ObjectMapper objectMapper = new ObjectMapper();
  16. @Override
  17. public String convertToDatabaseColumn(B b) {
  18. try {
  19. return objectMapper.writeValueAsString(b);
  20. } catch (JsonProcessingException ex) {
  21. // ...
  22. return null;
  23. }
  24. }
  25. @SneakyThrows
  26. @Override
  27. public B convertToEntityAttribute(String bVal) {
  28. try {
  29. return objectMapper.readValue(bVal, B.class);
  30. } catch (IOException ex) {
  31. // ...
  32. return null;
  33. }
  34. }
  35. }

这是持久化的 POST 方法:

  1. @Override
  2. @Transactional
  3. public A saveA(A a) {
  4. List<Map<String, String>> amts = new ArrayList<>();
  5. amts.add(....这里放入一些哈希映射...);
  6. a.getB_field.setAmts(amts);
  7. return repository.save(a);
  8. }

触发的查询是:

  1. insert into A (id, b_field) -> 这里的 b_field 已经包含了上面添加的值
  2. update A set b_field = ? where id = ? -> 同一个已经插入的对象。基本上是无用的

我可以想象这可能与事务提交有关,但不明白为什么它没有意识到没有任何更改。有什么想法吗?谢谢!

英文:

Im saving an Object that is POSTed in REST Webservice , but Im trying to update some fields just before that. I have an A class that has a B as its property (no relationship, just a field - complexity due to this field being a separate JSON field/object). I am trying to update B's property before A is persisted which actually works just fine.. EXCEPT after it inserts the new class , it also updates the field. Something like that:

  1. public class A {
  2. @GeneratedValue(strategy = GenerationType.IDENTITY)
  3. @Id
  4. Long id;
  5. @Lob
  6. @Convert(converter = BConverter.class)
  7. B b_field;
  8. }
  9. public class B {
  10. List&lt;String&gt; someVals;
  11. List&lt;Map&lt;String, String&gt;&gt; amts;
  12. }
  13. @Converter
  14. public class BConverter implements AttributeConverter&lt;B, String&gt; {
  15. private final static ObjectMapper objectMapper = new ObjectMapper();
  16. @Override
  17. public String convertToDatabaseColumn(B b) {
  18. try {
  19. return objectMapper.writeValueAsString(b);
  20. } catch (JsonProcessingException ex) {....
  21. return null;
  22. }
  23. }
  24. @SneakyThrows
  25. @Override
  26. public B convertToEntityAttribute(String bVal) {
  27. try {
  28. return objectMapper.readValue(bVal, B.class);
  29. } catch (IOException ex) {
  30. ......
  31. return null;
  32. }
  33. }
  34. }

Here is the POST method for persisting:

  1. @Override
  2. @Transactional
  3. public A saveA(A a){
  4. List&lt;Map&lt;String, String&gt;&gt; amts= new ArrayList&lt;&gt;();
  5. amts.add(....here goes some hashmap...);
  6. a.getB_field.setAmts(amts);
  7. return repository.save(a);
  8. }

Fired queries are:

  1. insert into A (id, b_field) -&gt; here b_field already contains the added values from above
  2. update A set b_field =? where id=? -&gt; same object that is already inserted. Basically useless

I can imagine it has to do with Transaction being committed, but dont understand why it doesnt get that there isnt any change. Any ideas? Thank you!!

答案1

得分: 0

似乎我自己离答案最近,至少目前是这样:
问题出在 Map 上打断了流程。涉及到 Maps 和 JPA 时有一些特殊情况,但直到现在在这种情况下仍然没有一个可行的方法。解决方法:如果我创建一个具有定义字段的类,而不是动态映射,它就能正常工作。<br>
更新:<br>
受到 @jccampanero 发布的链接的启发,我将 Map 更改为 JsonNode,并使用 JsonNodeFactory 动态构建节点。这个方法非常有效!

英文:

Seems like I came closest to an answer myself, at least for now:
it is the Map that breaks the flow. There are specialties when it comes to Maps and JPA, but still none of them worked for me till now in this case.
Workaround: If I create a class with defined fields instead of dynamic map it works great. <br>
UPDATE:<br>
Inspired by a link from @jccampanero, Ive changed Map to JsonNode and am building a node dynamically with JsonNodeFactory. That works like a charm!

huangapple
  • 本文由 发表于 2020年9月21日 22:44:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63994648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定