动态构造组合对象

时间:2017-11-07 17:55:23

标签: spring hibernate spring-mvc

我有一个由不同课程的多个对象组成的课程的评论表。学生应该每个月查看他注册的课程。数学,科学,历史本身就是表格,但我存储了外键Review表格,以便课程的每个评论都与相应的表格相关联。

注意:学生只能注册两门课程

@Entity
class Review{
//multiple time fields here here

@OneToOne(cascade=CascadeType.ALL,optional=true)
@JoinColumn(name="math_review_id")
Math m;

@OneToOne(cascade=CascadeType.ALL,optional=true)
@JoinColumn(name="science_review_id")
Science s;

@OneToOne(cascade=CascadeType.ALL,optional=true)
@JoinColumn(name="history_review_id")           
History h;

}

超级

 @MappedSuperclass
 class Course {
   @Id
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   @Column(name="id")
   int id;

   @ManyToOne(fetch = FetchType.LAZY, 
        cascade = { CascadeType.DETACH,
                    CascadeType.MERGE, 
                    CascadeType.PERSIST,
                    CascadeType.REFRESH },
                    )
   @JoinColumn(name = "student_id")
   private Student student;
 }

子类历史

@Entity
 class History extends Course{
//fields specific to history course
 }

子类数学

@Entity
class Math extends Course{
//fields specific to math course
}

学生班

@Entity
class Student{
//fields name,id,...
@OneToMany(mappedBy = "student", 
           cascade = CascadeType.ALL,
           fetch = FetchType.LAZY)
private List<Review> reviewsList;
}

我检查学生注册的课程并相应地初始化数学,科学,历史。我将一个Review对象传递给我的reviews.jsp并使用hibernate保存返回的@ModelAttribute.I不要初始化学生不是的课程注册。我认为未初始化的对象不会被保存但是即使没有初始化,hibernate也会生成空条目(我认为因为它们被映射到一个表并且在一个持久化的类中)。我需要帮助如何使用学生注册的课程动态构建Review对象。我当前的设计可能有流程,任何更好的设计建议都非常受欢迎(我在Java和hibernate方面的经验很少)

1 个答案:

答案 0 :(得分:0)

作为一个建议,我认为你应该厌倦了为每门课程创建课程。拥有一个类型为成员的Course类是不够的,可以是数学,科学或历史。即使该类型本身也可以是一个实体:CourseType,您可以在代码中输入条目,但不会有MathScienceHistory。相反,这些是在数据库中,而不是代码。

Review对象只会与Course互动。想一想当你添加另一门课程时你需要做的所有工作。您将不得不更新许多不同的文件,甚至在数据库中添加一个表格,我不相信您应该这样做。

我想你可能在课程类之间存在一些差异,并且在一个课程中将所有这些分开可能有点尴尬。但根据我的经验,这通常值得做,因为它大大减少了代码量,并允许在没有代码的情况下添加更多课程。

编辑我仍强烈建议您考虑重新评估每门课程1门课程的决定,但无论如何您的决定。目前还不清楚这个评论对象是什么。你说学生将只注册2门课程,所以我想其中有2门是空的。但是后来它让我感到困惑,因为你每门课程都有一门课,但是你在所有科目中都有一个过度的评论对象。我原本希望看到:

class EnrolementReview{
    Course courseA;
    Course courseB;
}

否则,如果您的评论取决于MathScience课程中的字段,我希望每个课程都有一个评论课程:

class MathReview {
    MathCourse course;
}

或者您可能有一个通用基类供审核

abstract class CourseReview<C extends Course> {
    C course;
}

如果你们之间有共同的功能。然后是一个SemesterReview课程,用于在一个学期中查看2个课程:

class SemesterReview{
    CourseReview review1;
    CourseReview review2;
}

至于dynamic composition,IMO我认为这种概念在静态类型语言中没有多大意义。你有建筑师模式和蛋糕模式等。有些编程语言在这个领域有一些不错的东西,比如Scala特性,但是它们的好处是非常有限的,在Java中你无法做的事情等待几个有点邪恶的类演员,但它完成了工作。

对于您作为开发人员可用的所有设计模式和方法的所有排列,我认为您可以更轻松地查看设计决策的某些输出,例如:

  • 我要写多少课?
  • 我是否可以在不编写代码和更改的情况下添加更多课程 数据库表?
  • 其他人可以理解我的代码吗?

上次修改 关于许多空字段是一个问题,你有一些选择。你有空字段(你似乎不喜欢),或者你做一些像封装变量类型作为一个实体(例如每个课程有一个字符串,整数,双打等列表),我已经看到使用过在许多不同的情况下相当多。这样做可以,但你确实延迟了一些可能已经编译到运行时的区域,因为你可能需要一个变量名为scienceCategory的整数等。如果你有一些结构化也可能很尴尬数据。一般来说,如果您真的不知道客户将如何使用您的系统,那么这种方法才会有用,因此您可以将更多内容暴露给他们使用。

然而,我个人最喜欢的,是遵循你的类的自然组成,并将变量系列封装到他们自己的类中,你期望它们不会总是适用,如果一个不适用所有其他类不会要么是。这些类是否存在的逻辑应该是非常明确的,它们应该是Optional<ScienceInformation>,或者你应该在某处返回boolean的某些方法,无论该选项是否存在。然后,可以对您创建的系统中的这些选项执行操作。只需要小心你不要创建太深嵌套的对象,这些对象由对象组成,这些对象由对象组成,(并不总是一个问题,但通常是这样)。

但实际上我并不认为你选择的方式非常重要,他们都不会给你一种轻松的感觉,即写一堂课给你。只需要考虑如何以一种不会导致无法维护的混乱的方式对这些实体(例如,课程)进行抽象。你显然对你的领域有一个非常全面的了解,但是你应该以一种方式编写你的代码:我(一个不知道一学期有多少课程的人)可以阅读代码然后在没有阅读的情况下找到它评论(这将是作弊),这个问题的答案是什么。