Springboot关系管理

时间:2017-06-03 10:53:30

标签: hibernate spring-boot thymeleaf

我有一个关于使用带有百里香和关系管理的springboot的问题。

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

OBJ1(多) - TO - (一)OBJ2(一) - TO - (多)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是否正确处理关系设置是正确的,至少在孩子需要更新的情况下是这样的。
  4. Hibernate会话的生命是什么?
  5. 注意:许多关系真的应该被称为少数 - 关系上的集合几乎总是少于10个。

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

1 个答案:

答案 0 :(得分:3)

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

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

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

  

即使我在表单控制器obj2Repo.save(obj2)中有@Post,当我尝试在associateObj1ToObj2中调用它时 - 本应保存的值(如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. 隔离可变形式与不可变形式属性。
  3. 通常我更喜欢(1)作为默认选择。我主张使用(2)的唯一情况是视图具有相当数量的只读字段,为用户提供上下文信息,并且它们只能改变属性总数的一小部分。

      

    springboot是否正确处理关系设置是正确的,至少在需要更新孩子的情况下是这样的。

    这不是一个引发关注的问题。很多确切地说,这种情况取决于我之前提到的其他因素。

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

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

      这取决于您的配置设置。

      Spring启动允许使用OpenSessionInViewOpenEntityManagerInView过滤器,这会将Hibernate会话的生命周期延长到Web请求已结束的时间点。在我看来,除了简单的原型之外你不应该使用它,因为它带有自己的问题,包括基于糟糕的假设或代码的性能和意外的插入,更新和删除。