我有一个Spring Data REST应用程序,Hibernate作为持久层。我有一个实体有两个不同的@ManyToOne
引用。这是我的映射:
@Entity
public class Menu {
@Id
@GeneratedValue
private Long id;
@ManyToOne
private Menu parent;
@ManyToOne
private Resource resource;
}
我有几个Spring Data存储库:
public interface MenuRepository extends CrudRepository<Menu, Long> {}
public interface ResourceRepository extends CrudRepository<Resource, Long> {}
我想将parent
实体实例的resource
和Menu
引用链接到现有实体。我发送以下请求:
PUT http://localhost:8080/menus/2/resource
{"_links":{"self":"http://localhost:8080/api/resources/2"}}
PUT http://localhost:8080/menus/2/parent
{"_links":{"self":"http://localhost:8080/api/menus/1"}}
问题是,只有一个(随机的)引用被附加,另一个引用null
。
原因:
根据Hibernate SQL日志判断,Hibernate生成的更新查询都会更新所有字段,甚至是那些未更改的字段,并且这些并发更新会相互覆盖:
update menu set parent_id=1, resource_id=null where id=2
update menu set parent_id=null, resource_id=2 where id=2
解决方法:
如果我向实体添加@DynamicUpdate
注释,则生成的SQL仅限于更改的属性:
update menu set resource_id=2 where id=2
update menu set parent_id=1 where id=2
这解决了这个问题。但它似乎是一个非常脆弱和模糊的解决方案。
我的问题:
是否还有其他(最好是交易性的)惯用解决方案 使用Spring Data更新多个嵌套引用的问题 REST,无需发送两个单独的HTTP请求?
如果我使用两个单独的PUT请求,我希望它们是幂等的, 无论如何,都应该由REST层处理幂等性 底层持久层的。意识形态显然是 在这种情况下违反了。这是Spring Data REST的错误/功能吗? Hibernate,还是两者的结合?
也许我错过了其他的东西,或其他一些解决方案,这根本不应该发生?