I am trying to build a Book app.
The entities are so-
The Entity User has a field called Role which specifies if this is an Author or Reviewer. Currently, I am using an Enum data member to differentiate if the User is an Author or Reviewer. One single instance of a User cannot be both.
A Book will have 1...* Authors- So a User entity which is an Author will have a many-to-many relation with entity Book
A Book will have 1...* Reviewers- So a User entity which is a Reviewer will have a many-to-many relation with entity Book
I was wondering how would I implement the User side - I preferably want one single collection of Books- If the User is an Author, this will contain a reference to the books he has authored. If it is a reviewer, it will contain references to the books on which he is a reviewer.
I am wondering if there is any construct in JPA/ Hibernate which can enable this.
I could always implement Author and Reviewer as different entities, but I still want to know the answer to such a situation which I presume must be quite commonly encountered.
Related
I'm working on a project for university that requires me to implement a basic Paypal-like money transfer system. I'm currently modelling the relationships between entities. My current problem involves 2 entities: User and Transaction.
The logic is that a Transaction has a sender User and a recipient User, and the amount of money sent. I'm struggling with modelling this relationship however as I can't figure out the correct way of forming the relationship between User and Transaction.
Is it correct to have 2 seperate one-to-one relationships on the Transaction entity which references the same attribute on the User but with a different column name on the database table?
This is a classical situation: two Entities are connected by two different relationships. In this case you have a one-to-may relationship Send between User and Transaction, and a one-to-many relationship Receive between User and Transaction.
And you should treat them as any other relationship for what concerns the implementation. For instance, in a relational database you can have a table Users with its attributes, and a table Transactions with, in addition to the amount of money and other relevant information, two different attributes, sender and receiver, both of which foreign keys for the table User.
For a JPA project I got asked to implement the following situation:
A book can have many authors.
Also there is an UML that states that an author can have many books and a book can have many authors.
I am a beginner when it comes to this subject.
Do I need an many to many relation (with an intersection table)
or do I need a bidirectional one to many relation.
Also the bidirectional part of a one to many relation confuses me. If anybody could explain this with an example that would be nice.
The bidirectional associations allow you to navigate both sides of this relationship both in Object space as well as in JPA/Hibernate Query Language.
In your example, a database many-to-many association is mandatory (meaning you have a BOOK, an AUTHOR and a BOOK_AUTHOR link table). Hibernate offers two possibilities for mapping this relationship:
You can model this with two entities: Book and Author, each one having a #ManyToMany association to the other (one being the owning side while the other being the inverse one)
You can have three entities: Book, Author and BookAuthor and this time Book have a #OneToMany association to BookAuthor and Author has also a #OneToMany association to BookAuthor. This option allows you two map additional link table columns (BOOK_AUTHOR creation_time).
I am going to use ElasticSearch for as the search repository in my application.
I have a few questions regarding what is best practice when it comes to organizing
objects in the search index when the objects have associations/relations to each other.
From what I know search indexes is a flat structure and doesn't work with the concept of
relations in the same way as a database.
Let say you have these domain objects:
Person:
- Has a one-to-many relationship with Car
Car:
- Is owned by one Person, many-to-one with Person
Department:
- Each Department have many People and each Person may belong to many Department, many-to-many
What would be the best way to store this in the search index? What are the options? For instance I want to find all the people belonging to a certain deparment, or all people where the car has more than 300 bhp.
I am using the Java client API if it matters.
Elastic search (or Lucene) isn't a relational database, so you would need to flatten your relationship model.
Try to model a view that gets this structure -
Car|Person|Department
This will give you all attributes required to lookup a car. This can be imported into a document for Car.
Similarly
Person|Department
will give you all information for a person. This will help you lookup a Person
Department can be a third document.
You can have multiple documents for each entity. But the relationship needs to be translated as a property of the entity.
I need help in modeling a set of tables/classes in my project. I also need help on how to do the hibernate mapping for these tables. I have following tables in my project.
Person
Organization
Contact
Address
Person table can have one or more addresses. Organization and Contact can have only one Address. So I have added the following columns to establish the relationship between the tables.
Address table has PersonId [Since one Person can have more than one address].
Organization and Contact table has AddressId [Since these tables can have only one address].
I want to know what java classes I need to create for these tables. Currently I have Person, Address, Organization and Contact classes. Not sure how to link Address class to Person, Organization and Contact class.
I want to know whether I should consider Address as a Component or an Entity. And how create the xml mapping Address is considered as a Component.
The PersonId in Address table may have null values for the Address records created for Organization and Contact. I fine with creating a separate table [say Person_Address] to store list of addresses for a person. But having this link table might give an provision for many to many relationship between Person and Address tables. How do I enforce one to many relationship in this case.
I would go for what you suggest in 3.
By using a OneToMany relationship on the set of addresses in the Person class the intermediate table will be created automatically and I guess it will have a unique constraint on the address id.
Edit: You will only get a reference in the address table if you add a corresponding many-to-one annotation in the address class and use the and map the one-to-many annotation to that field. But since your not doing that you'll get a Person_Address table even with a one-to-many relationship without creating any extra classes.
You should model your classes like you would in plain java. I.e Person would have a set of addresses, the others will have just one and the Address class is oblivious of the others.
Then you add a #OneToMany annotation in the Person class and #OneToOne class in the others. Or you put that in your orm.xml, although annotations is much better for maintenance.
As for Component/Embedable vs Entity I would suggest entity as it is the simplest and no limitations. Don't use to many concepts at once, and stick to the main road.
The below definition is taken from Hibernate association mapping tutorial here
Each book is related to one publisher while one publisher may publish many books.
I'd represent the above definition the below way in Java
class Book
{
Publisher pub;
}
class Publisher
{
Set<Book> books;
}
Question 1. Now I am confused as to why the tutorial says The association from book to publisher is called a “many-to-one” association. I thought There is a "one-to-many" association between the publisher and the book would have been the right approach.
Question 2. Below is the hbm for Book. Why shouldn't we declare a one-to-many in the Publisher's hbm mapping. What determines the location for this relationship mapping?
<class name="Book" table="BOOK">
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" />
</class>
it depends on whether the relationship is bidirectional. See section 7.3.2 here http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/collections.html#collections-mapping.
a bidirectional relationship is when you can go from both the parent to the child (i.e. Publisher -> Book) and from child to parent (i.e. Book -> Publisher). The parent to child is a one-to-many, while the child to parent is a many-to-one.
Note you do not need bidirectional relationships. The 'right approach' depends exactly on what your application needs. If you need to only go from pu.lisher to book, you only need a one to many. If you only need to go from books to publisher, that you just need the many to one. If you need both, you can have both (i.e. make the relationship bidirectional)/
The association from Book to Publisher is many-to-one because there can be many books per publisher. This is irrelevant to the that fact that Book is only aware of its own Publisher. The association is to aid Hibernate in understanding the underlying representation.
There is nothing wrong with also declaring a one-to-many relationship from Publisher to Book. You can have both present. It depends on your data model and how you plan on interacting with it.
Question 1: Actually both are correct. It depends on the direction of the relationship. Many books belong to one publisher results in a many to one relationship from the book side.
Question 2: If you are interested in a bi-directional relationship then you can actually place a one to many on one side and a many to one on the other. However, you have to be careful to use the mappedBy attribute to ensure that hibernate knows that its the same relationship being defined from both ends.
A relationship can be unidirectional, or bidirectional.
The way you designed it in your Java code, it's bidirectional. This means that the same physical relationship (materialized by the foreign key) is viewed as two logical relationships :
from the book point of view : several books are published by one publisher (ManyToOne)
from the publisher point of view : one publisher publishes several books (OneToMany)
The XML mapping you show in your question describes one side of the relationship. But if you want to make it bidirectional, you must also declare the other side. One of the sides is declared as the inverse of the other.
Hibernate gives you the choice : you could have a collection of books in the publisher class (unidirectional one to many), or a publisher reference in the book class (unidirectional many to one), or both (bidirectional one to many/many to one).
Read the documentation for more details.