【问题标题】:Springboot relationship managementSpring Boot 关系管理
【发布时间】:2017-11-04 16:52:36
【问题描述】:

我有一个关于将 springboot 与 thymeleaf 和关系管理一起使用的问题。

我有三个需要完全双向的对象:

obj1(Many)--TO--(One)obj2(One)--TO--(Many)obj3

他们已经设置好了:

public class Obj1 {
@Id
private long id;
@ManyToOne(cascade=CascadeType.ALL)
private Obj2 obj2;

public class Obj2 {
@Id
private long id;
@OneToOne
private User planUser
// Other fields
@OneToMany(mappedby = obj2)
private List<Obj1> obj1;
@OneToMany(mappedby obj2)
private List<Obj3> obj3;

public class Obj3 {
@Id
private Long id;
@ManyToOne
private Obj2 obj2;

在视图方面,有一个名为 view1 的页面,用于填充 Obj1。这行得通。

还有一个名为 view2 的页面: 1. 显示来自 Obj1 的一些基本细节 2. 填充/更新 Obj2 和 Obj3

问题在于提交 view2 以更新/创建 Obj2 和 Obj3。

我试图让控制器调用 Obj1 服务上的方法:

@Override
@Transactional
public Obj1 associateObj1ToObj2(Long Obj2Id, Obj1 newObj1) {
    final Obj2 obj2 = ojbj2Repository.findOne( obj2Id );
    obj2.getObj1().add( newObj1);
    newObj1.setObj2( obj2 );
    return obj1Repository.save( newObj1 );
} 

问题:

  1. 即使当我尝试在 associateObj1ToObj2 中调用表单控制器 obj2Repo.save(obj2) 中的 @Post 时,本应保存的值(如 userPlan)却没有。为什么?
  2. 在上述情况下,单个根对象是否可以并且应该为多个页面提供服务? (建议的替代方案显然是创建一个混合类来用于支持像 view2 这样的页面 - 链接到 git 示例很棒(这是否称为 DTO))。
  3. springboot不会处理关系设置是否正确,至少在childs child需要更新的情况下)
  4. Hibernate 会话的生命周期是什么?

注意:许多关系确实应该被称为少数 - 关系上的集合几乎总是少于 10。

这个答案似乎部分相关:Could not initialize proxy - no Session

【问题讨论】:

标签: hibernate spring-boot thymeleaf


【解决方案1】:

我打算在这里讨论使用基于 conversation 的支持框架的双方,但是,我认为事后看来这无关紧要。虽然这些框架可以帮助最终处理视图/控制器/域对象一致性所需的样板,但我认为这不会改变您应该如何设计控制器和视图以与用户交互。

我想说大多数开发人员经常采取将他们的实体 bean 发送到作为支持 bean 表示的视图的立场。对于小型、非复杂的 imo 播放项目就足够了,但通常当实体关系或 UI 布局变得复杂时,这种方法开始失效。

通过使用非实体作为视图的支持 bean,您可以让 UI 和视图有机地增长,而不受为数据库表和持久性关系建模的决策和选择的限制。这也意味着您可以利用数据库模式设计选择,而不会影响您在 UI 中布局和与用户交互的方式。这在重构代码或通过 UI 更改改善用户体验时非常有用。

即使当我尝试在 associateObj1ToObj2 中调用它时,表单控制器 obj2Repo.save(obj2) 中有 @Post,但应该保存的值(如 userPlan)却没有。为什么?

表单是否真的在帖子中发回了这些信息?

假设我们有一个非常简单的对象:

class SomeEntity {
  private Integer id;
  private String name;
  private String address;
  private List<String> nicknames;
}

如果所有表单都允许用户更改他们的地址,但表单实际上并没有将name 的值发回给我们,那么当我们在控制器中检查SomeEntity 实例时,它将为空。这真的是我们想要的吗?如果你有一段关系,也会发生同样的情况。如果表单实际上没有将昵称列表发回给我们,那么这种关系也将是空的。

对我来说,这突出了为什么视图的支持 bean 最终应该代表视图的用例,而且仅此而已。我们确切地知道视图需要和返回哪些字段,并且我们管理该数据的生命周期,独立于我们的实体模型需要在我们的应用程序和持久性提供者的角度被认为是有效的数据。

在上述情况下,单个根对象是否可以并且应该为多个页面提供服务? (建议的替代方案显然是创建一个混合类用于支持像 view2 这样的页面 - 链接到 git 示例很棒(这是否称为 DTO)。

这只是一种偏好设计选择。视图的单个支持 bean 非常好。不过,有理由考虑使用多个支持 bean:

  1. 将您的视图视为较小部分的组合。
    这允许在其他 UI 布局中重复使用这些组件的代码。
  2. 隔离可变和不可变的表单属性。

通常我更喜欢 (1) 作为默认选项。我唯一提倡使用 (2) 的情况是视图有相当数量的只读字段为用户提供上下文信息,并且它们只能改变属性总数中的一小部分。

springboot不会处理关系设置是否正确,至少在childs child需要更新的情况下)

这不是弹簧启动问题。正如我之前提到的,这在很大程度上取决于其他因素。

  1. 哪些数据在表单中被序列化并反过来发送回控制器。
  2. 表单是如何组织的,是否正确序列化。
  3. 您是否使用对话框架/配置。

Hibernate 会话的生命周期是什么?

这取决于您的配置设置。

Spring boot 确实允许使用 OpenSessionInViewOpenEntityManagerInView 过滤器,这将 Hibernate 会话的生命周期延长到 Web 请求已经结束。在我看来,除了简单的原型之外,你永远不应该使用它,因为它会带来一些问题,包括性能和基于不良假设或代码的意外插入、更新和删除。

【讨论】:

  • 非常有帮助 - 我也对休眠魔法的细节感到困惑
猜你喜欢
  • 2017-05-29
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 2015-09-17
相关资源
最近更新 更多