5

For an excercise I need to build something like :

For a course I need to create a review that is made up out of certain reviewlines and feedbackscores.

This review object (unique instance) needs to be filled in by a list of customers.

Depending on the course the review is for, the review will change (e.g.for one course the number of reviewlines and feedbackscores will change). Each customer can be enrolled in more then one course and each review is specific for him.

enter image description here

Now how do I need to see the relationsship between "review" object (unique instance) and "customer" if I want to use JPA to save this all to the db?

  • A customer can have more then one review he/she needs to fill in.
  • A certain review object needs to be filled in by many customers (but this is a review object with a certain build [reviewlines and feedbackscores]) and unique for him.

Maybe I see it to complex but what is the best way to build this?

Matt
  • 74,352
  • 26
  • 153
  • 180
Darth Blue Ray
  • 9,445
  • 10
  • 35
  • 48

3 Answers3

1

Try the following:

ER/Class diagram

I think it's covered all your design points.

I am trying to read between the lines of your comments, and I think you want to implement a system where you capture a number of 'rules' for the Review (I'm guessing, but examples may be that reviews can be up to n lines, there must be at least m CustomerReviews before the Review gains a degree of quality). If this is indeed the case, I have created a ReviewTemplate class:

  • ReviewTemplate would have attributes/columns for each of value you would need. These attributes/columns are duplicated on Review
  • Populate ReviewTemplate with a number of rows, then create a row in Course and link it to one ReviewTemplate
  • When a Course needs a Review, copy the fields from the ReviewTemplate into the Review
  • In Java, implement the business rules for Review using the copied values - not the values on ReviewTemplate.

Why copy the values? Well, I bet that at some point, users want to edit the ReviewTemplate table. If so, what happens to the Review objects using the edited ReviewTemplates? Does the modified value on ReviewTemplate somehow invalidate past Reviews and break your business logic? No, because you copied the rule values to Review and so past Reviews will not change.

EDIT: Answers to specific questions

How do you see the duplicating? I can create an entity ReviewTemplate with the specified attributes. In this entity there will be a relationship with reviewlines and feedbackscores.

I see each ReviewTemplate as holding prototypical values for a particular 'type' of Review, which just might include a default reviewLine (but that might not make sense) and a default feedbackScore. When you create the Review, you would do the following:

  1. Instantiate the Review and populate with values from ReviewTemplate
  2. Instantiate as many CustomerReview objects as you need, linking them to the relevant Customer objects (I infer this step from your previous comments. It might also make sense to omit this step until a Customer voluntarily elects to review a Course)

    1. (If appropriate) Populate the CustomerReview attribute feedbackScore with the default value from ReviewTemplate
    2. Instantiate CustomerReviewLine records as appropriate

If you follow this approach, you do not need to add a relationship between ReviewTemplate and CustomerReviewLines.

When I e.g. state that customers 1 to 4 need to fill in the review 4 specific "objects" need to be created that will hold the information and also 4 sets of the needed reviewlines and feedbackscores need to be created so they all can hold the information.

Absolutely.

I just don't know how to implement this is a JPA structure so the information is hold in the db ... ?

JPA allows you to attack the problem in many ways, but the best practice is to manually create both the DB schema and the Java classes (eg see https://stackoverflow.com/a/2585763/1395668). Therefore, for each entity in the diagram, you need to:

  1. Write SQL DDL statements to create the table, columns, primary key and foreign keys, and
  2. Write a Java class denoted with the @entity annotation. Within the class, you will also need to annotate the id (primary key) with @id and the relationships with @OneToMany or @ManyToOne (theirs additional parameters in the annotation to set as well).

Now, on the JPA side, you can do things like:

ReviewTemplate template = course.getReviewTemplate(); //assuming the variable course
Review review = new Review();
review.setCourse(course);
review.setRuleOne(template.getRuleOne());
// Copy other properties here

EntityManager em = // get the entity manager here
em.persist(review);

// Assume a set or list of customers
for (Customer customer : customers) {
    CustomerReview cr = new CustomerReview();
    cr.setReview(review);
    cr.setCustomer(customer); 
    cr.setFeedbackScore(template.getDefaultFeedbackScore());
    // set other CustomerReview properties here

    em.persist(cr);

    // You can create CustomerReviewLine here as well

If written inside a standard EJB Session Bean, this will all be nicely transacted, and you will have all your new records committed into the DB.

EDIT 2: Additional question

(I'm assuming that the second comment completely supersedes the first)

So when I create a reviewtemplate and I link it to a bunch of customers I write the template to the db and create a bunch of reviews based on the template but linked to the specific customer and with his own unique reviewlines and feedbackscores. Like I see it now the reviewline (more a question or discription) is the same for each review (of a template), it is only the score that changes between the customers

I finally think I understand ReviewLine. I had thought it a place where the Customer enters lines of text the comprise the CustomerReview. I now believe that ReviewLine is a specific question that the Customer is asked, and which the Customer provides a feedbackScore.

With this understanding, here is an updated ER/Class diagram.

enter image description here

Note that there are some significant changes - there are several more tables:

  1. ReviewLineTemplate provides a place for template questions to be stored on a ReviewTemplate
  2. When a Review is instantiated/inserted (which is a copy of a specific ReviewTemplate), the ReviewLineTemplates are copied as ReviewLines. The copy operation allows two important features:

    1. On creation, a Review and its ReviewLines can be customized without affecting the ReviewTemplate or ReviewLineTemplate
    2. Over time, the ReviewTemplate and ReviewLineTemplate can be updated, edited and continually improved, without changing the questions that the Customer has already answered. If CustomerFeedbackScore were linked to ReviewLineTemplate directly, then editing the ReviewLineTemplate would change the question that the Customer has answered, silently invalidating the feedbackScore.
  3. FeedbackScore has been moved to a join-table between ReviewLine and CustomerReview.

Note that this model is fully denormalised which makes it more 'correct' but harder to build a GUI for. A common 'optimization' might be to introduce:

  • 10 (say) columns on ReviewTemplate and Review called reviewLine1 through reviewLine10.
  • 10 (say) columns on CustomerReview called feedbackScore1 through feedbackScore10.
  • Remove the ReviewTemplateLine, ReviewLine and CustomerReviewLine tables

Doing so is not normalised, and may introduce a set of other problems. YMMV

Community
  • 1
  • 1
Andrew Alcock
  • 19,401
  • 4
  • 42
  • 60
  • How do you see the duplicating? I can create an entity ReviewTemplate with the specified attributes. In this entity there will be a relationship with reviewlines and feedbackscores. When I e.g. state that customers 1 to 4 need to fill in the review 4 specific "objects" need to be created that will hold the information and also 4 sets of the needed reviewlines and feedbackscores need to be created so they all can hold the information I just don't know how to implement this is a JPA structure so the information is hold in the db ... ? – Darth Blue Ray Feb 14 '13 at 23:50
  • First of all thx for the reply. I'm still not with you. I create a class/entity reviewTemplate. The difference between te templates are the number of and values of the reviewlines and feedbackscores. Depending on the amount of lines I could create a review with the specified amount of lines and the value's of the template (e.g. name, startdate, ..) Why do I not need to create a relationship between review and lines. The lines are not in the review and unique for each object so I do need to link those and write the to the db so I can retrieve them? I hope this makes any sense – Darth Blue Ray Feb 15 '13 at 13:52
  • So when I create a reviewtemplate and I link it to a bunch of customers I write the template to the db and create a bunch of reviews based on the template but linked to the specific customer and with his own unique reviewlines and feedbackscores. Like I see it now the reviewline (more a question or discription) is the same for each review (of a template), it is only the score that changes between the customers. – Darth Blue Ray Feb 15 '13 at 14:00
  • First of all, thx again for all the effort. True, you see it right! I now see the reviewlines as a number of questions in the template the customer need to set a feedbackscore to. Because all the reviewlines are the same for all the customers and only there feedbackscores are different this solution is usable. I agree the normalisation is a total different issue ... . But first of all, I will try to get this working because the excercise is more from a JPA, servlet, jsp perspective ... . – Darth Blue Ray Feb 17 '13 at 14:23
1

The structure of data always depends on the requirements, and there never exists a "one-and-only" solution. So, do you need maximised atomiticy or a high performance data system?

The fastest and easiest solution would be not using a database, but hash tables. In your case, you could have something like 3 hash tables for customer, review, and probably another one for the n:n relationship. Or if you're using a database, you could just store an array of the review-primary-keys in one field in the customer table.

However, we all learn in school to do atomicity, so let's do that (I just write the primary/foreign keys!):

  • Customer (unique_ID, ...)
  • Review (unique_ID, ...)
  • Customer_Review (customer_ID, review_ID, ...) --> n:n-relationship

The Customer_Review describes the n:n-relationship between customers and reviews. But if there is only one customer per review possible, you'll do that like this:

  • Customer (unique_ID, ...)
  • Review (pk: unique_ID, fk: customer_ID, ...) --> 1:n-relationship

However, I suggest you need to learn ERM as a good starting point: http://en.wikipedia.org/wiki/Entity_relationship_model

Marcus
  • 1,222
  • 2
  • 13
  • 22
0

You need a ManyToMany relation :

  • One customer -> several reviews.
  • One review -> several customers.

So you will have 3 tables in your database schema : Customer, review and a junction table with the customer ID and the review ID.

See Wikipedia : Many to Many

Jonathan
  • 111
  • 9
  • The problem with this is that if I build a review with revieuwlines and feedbackscores. This review object needs to be filled in by the customers. But each customer needs to fill in his own review object. – Darth Blue Ray Feb 12 '13 at 10:01
  • Where's your problem ? The junction table will permit 2 operations : Getting the reviews assiciated with a particular Customer, and getting the customers who need to fill a particular review. – Jonathan Feb 12 '13 at 11:05
  • For example : I create a review object with 5 reviewlines and feedbackscores. This review needs to be filled in by customer 1 to 4. I create another review object with 3 reviewlines and feedbackscores. This review need to be filled in by customer 1 to 3. for each customer the specific review is unique. It's not something like a book can have many authors and a author has many books (here the book stays the same). In this case the specific review needs to be filled in by the specific customer. it's not one review that is linked to many customers – Darth Blue Ray Feb 12 '13 at 19:07
  • Ok, are you trying to say that a reviewline is what is created when a customer fills in the review ? If it's ok, the reviewline table should have a Many-to-One relation with customers. This is to retrieve the author. The Many-to-Many link between customers and review doesn't provide an "author" information, but a "have to fill in" information. I'm sorry, my english is not very good but I do my best to understand you. – Jonathan Feb 12 '13 at 22:38
  • I mean if you have like a many to many between Book and author (a book can have 1 or more authors and a author can have zero or more books he has written) you speak over the same book and the same author for this relationship. In this case if I make a review (with his collection of reviewlines and scores) this is more like a review type. This review type must then be duplicated over the amount of customers you want to have that the list of customers need to fill in. Each customer has a specific review only he need to fill in. Another custormer has nothing to do with his review – Darth Blue Ray Feb 13 '13 at 10:41
  • The problem is that not each reviewtype is the same. A review over something will have some reviewlines another revieuw will have other review lines. So I think it will be better to create a reviewtype and then create reviews of a certain type that I link to the customers. If a customer need to fill in another reviewtype I need to create a new type and create reviews of this type and link this again to those customers that must fill in this review. Another solution is not possible because the fact that not all reviews are the same, only those of a certain "type". – Darth Blue Ray Feb 13 '13 at 10:45