The hibernate documentation gives some rules when we use one-to-many association in Hibernate:
http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/collections.html#collections-onetomany
A one-to-many association links the tables of two classes via a
foreign key with no intervening collection table. This mapping loses
certain semantics of normal Java collections:
An instance of the contained entity class cannot belong to more than
one instance of the collection.
An instance of the contained entity
class cannot appear at more than one value of the collection index.
Please help me in understanding these statements.
Suppose I have a Product and it has collection of parts, now as per the points what kind of restrictions applied on my Product and its parts?
A Part cannot belong to 2 or more Products
A Part cannot appears more than one time in the Collection of Parts of a Product
Related
I am new to ORM and got stuck on the following issue (simplified for the discussion here):
I am modelling a tournament, with competitors and disciplines. Both have their own entity class. Competitors compete in each discipline exactly once, and receive a score. As long as a competitor has not yet competed in a given discipline, there is no score.
Data Model:
A straightforward DB design would be a scores table with foreign keys to both the competitors table and the disciplines table. That is, I would set up two one-to-many relationships, plus integrity constraints on the foreign keys - I cannot delete a competitor or a discipline as long as there are scores that reference either one.
But how do I map this 2D Array (competitors/disciplines) onto my classes? I am using Java and Hibernate.
My current solution is to put a collection of scores into the Competitor entity class, and similarly for the Disciplines class. This creates a bidirectional relationship with a join table for each of the two entity classes. Is this the recommended way to do the mapping?
It does map the relationship form the perspective of each domain class, but it misses out on the 2D array structure. I want to output the entire array - on a UI, for example - with rows for competitors, columns for disciplines, and the scores in the corresponding table cell. Building such an output from the entity classes as just described is tedious and requires (a) to iterate through the competitor collection and then (b) look up the corresponding discipline - or the other way around.
Ideally, I would like to have a hash map with two keys, like the Guava Table, or a nested hash map. I suppose that there is no native Hibernate mapping for this kind of advanced collection. But maybe there is a best practice how to implement it using custom queries?
But how do I map this 2D Array (competitors/disciplines) onto my classes? I am using Java and Hibernate. My current solution is to put a collection of scores into the Competitor entity class, and similarly for the Disciplines class. This creates a bidirectional relationship with a join table for each of the two entity classes. Is this the recommended way to do the mapping?
IIRC, an implicit join table doesn't allow to add the score. Even if it did, I would't like it as the scores are actually the main information. So I'd go for an explicit table.
class Score {
#ManyToOne(optional=false)
Competitor competitor;
#ManyToOne(optional=false)
Discipline discipline;
}
This should provide everything you need. You may also want a Set<Score> or even Map<Discipline, Score> in the class Competitor (and vice versa in the other class), but you may not need it. The mapping would probably use #ManyToMany(mappedBy="competitor") and #MapKey... I haven't used it for long as I found out I don't really need it.
Ideally, I would like to have a hash map with two keys, like the Guava Table, or a nested hash map.
Using the default #ManyToOne(fetch=EAGER), the needed competitors and disciplines get fetched automatically using a JOIN. I'm afraid, a List is all you can get, but iterating it once and filling a Guava Table is trivial:
list.stream()
.forEach(score -> table.put(score.competitor, score.discipline, score));
Just don't forget that the entities are mutable but mustn't be mutated when used as keys. Obviously, you should only fetch the entities you need rather than filtering the Table. However, once you have the Table, you can use all its operations at will; Hibernate won't help you here anymore, but you don't need it (and you don't want to hit the DB again).
I have an issue in performing Hibernate Mapping. The scenario is as follows:
There is a User class which has username, name, dateofbirth, image and other information pertaining to a user with username as the primary key.
Second class is Product class which has product id and other information related to a product with primary key as product key.
The third class is Order class which has OrderId, OrderDate, Username- should be foriegn key-referring to the User class username and finally a Set of type Product- because one order can have many products.
Now I want the primary key of the Order class as a composite key (OrderId, ProductID) and this productID should be reference from Product Class.
The relationships that I want to create are as follows:
1. One order can belong to only one User
2. One order can have many products
Can someone lead me on how to go about it? Any kind of help will be great.
I think most likely you are thinking similar relationship. Difference in your requirement is you need One to Many mapping from Order/PurchaseOrder to Product/Item and you don't want Shipment.
My suggestion would be:
Create bi-directional one-to-many relationship b/w User and Order. Benefit for bidirectional is you can access User Object from Order Object, if not required, you can keep it unidirectional from User to Order.
Create one-to-many relationship b/w Order and Product.
Instead of composite key in order, keep the primary key as just OrderID. You can still fetch list of products from your order object and order object from user object.
The whole point in making this decision is from which object you derive remaining objects. With ORMs you should know from which object you would derive rest and so my suggestion is based on assumption that you will have User object available as attached entity, so you can get list of orders (defined as set) and from a particular order find out list/set of Products.
In case you have Order object available first, then create a bidirectional with User. So that you can find list/set of Products at one end, and Customer associated at other.
For ORM mappings refer Hibernate Mapping Examples.
Hope this clarifies.
Reading a wiki page about Hibernate I elaborated some perplexing conclusions:
1) Bidirectionality is reccomended in one-to-many
2) Bidirectionality is optional in many-to-one
3) Bidirectionality is normally present in many-to-many
4) Unidirectionality is reccomended in one-to-one relationships,
using as owner class the one with the primary key of the
relation (not the foreign key).
Are these statements true? Do you have any example to explain why in some cases unidirectionality is reccomended and in others bidirectionality is reccomended instead?
Here's the wiki page (read under "concepts"):
http://wiki.elvanor.net/index.php/Hibernate
Note that "bidirectionality" in the context of Hibernate means that in your Java classes, both sides of the relationship maintain a link to the other side. It has no impact on the underlying database schema (except in the case of indexed collections, see below), it's just whether or not you want the Java side to reflect that.
For all of your conclusions, "recommended" actually translates to "it usually ends up making sense, given your business logic, that you'd do it this way".
You really want to read through chapters 7 and 8 of the Hibernate Core Reference Manual.
It's recommended if you need it. A lot of convenience comes from specifying a bidirectional relationship; particularly it becomes possible to navigate the relationship from both ends in your business logic. However, if you don't actually need to do this, there's nothing to gain. Use whatever is most appropriate for the situation. In practice I've found that I want to specify both ends of the relationship to Hibernate more often than not -- but it is not a rule, rather, it reflects what I want to accomplish.
This is true. In a many-to-one (or one-to-many) relationship, it is optional. Consider the following schema:
table: users
fields: userId, userName
table: forumPosts
fields: postId, userId, content
Where forumPosts.userId is a foreign key into users. Your DAO classes might be (getters/setters omitted for brevity):
public class User {
private long userId;
private String userName;
}
public class ForumPost {
private long postId;
private User user;
private String content;
}
As you can see, this is a unidirectional many-to-one relationship (ForumPost-to-User). The ForumPost links to the user, but the User does not contain a list of ForumPosts.
You could then add a one-to-many mapping to User to make it have a list of ForumPosts. If you use a non-indexed collection like a set, this has no impact on the database schema. Merely by specifying both sides to Hibernate, you have made it bidirectional (using exactly the same schema as above), e.g.:
public class User {
private long userId;
private String userName;
private Set<ForumPost> forumPosts;
}
public class ForumPost {
private long postId;
private User user;
private String content;
}
Hibernate will now populate User.forumPosts when necessary (essentially with SELECT * FROM forumPosts WHERE userId = ?). The only difference between bidirectional and unidirectional here is that in one case Hibernate fills a set of ForumPosts in User, and in the other case it doesn't. If you ever have to get a collection of any given user's posts, you will want to use a bidirectional relationship like this rather than explicitly constructing an HQL query. Depending on your inverse/insert/update/cascade options in your relationship, you can also add and remove posts by modifying the User's set of posts, which may be a more accurate reflection of your business logic (or not!).
The reason I specified that non-indexed collections don't impact the underlying schema is because if you want to use an ordered, indexed collection like a list, you do have to add an extra list index field to the forumPosts table (although you do not have to add it to the ForumPost DAO class).
This is true, but is not a requirement and it's deeper than that. Same as above. Bidirectionality is usually present in many-to-many. Many-to-many relationships are implemented with a third join table. You specify the details of this table on both sides of the relationship. You can simply not specify the relationship on one side, and now it's a unidirectional relationship. Again, whether or not you tell Hibernate about the mapping is what determines if its unidirectional or bidirectional (in the context of Hibernate). In this case it also has no impact on the underlying schema unless you are using an ordered index collection. In fact, the many-to-many example in the Hibernate reference manual is a unidirectional setup.
In reality, it would be odd to have a unidirectional many-to-many relationship, unless perhaps you are working with an existing database schema and your particular application's business logic has no need for one of the sides of the relationship. Usually, though, when you've decided you need a many-to-many relationship, you've decided that because you need to maintain a collection of references on both sides of the relationship, and your DAO classes would reflect that need.
So the correct conclusion here is not merely that "bidirectionality is normally present in many-to-many", but instead "if you've designed a database with a join table, but your business logic only uses a unidirectional relationship, you should question whether or not your schema is appropriate for your application (and it very well may be)".
This is not true. Exactly the same as all the points above. If you need to navigate the one-to-one relationship from both sides, then you'd want to make it bidirectional (specify both sides of the mapping to Hibernate). If not, then you make it unidirectional (don't specify both sides of the mapping to Hibernate). This again comes down to what makes sense in your business layer.
I hope that helps. I left a lot of intricacies out. You really should read through the Hibernate documentation - it is not organized particularly well but Chapter 7 and 8 will tell you everything you need to know about collection mapping.
When I'm designing an application and a database from scratch, personally, I try to forget about Hibernate and the database entirely. I set up my DAOs in a way that makes sense for my business requirements, design a database schema to match, then set up the Hibernate mappings, making any final tweaks to the schema (e.g. adding index fields for ordered collections) at that point if necessary.
I'd like to explore Hibernate and used it in my project instead of JDBC.
My table design is highly normalized.
Suppose, I have this use case: Each insurance applied by a customer has one associated rateplan. Usually, in RDBMS this is implemented using two tables like below.
Table Insurance:
id long;
accountHolder varchar;
ratePlanId int; -->Rate Plan Id is Foreign Key to the RatePlanTable
Table RatePlan:
ratePlanId int;
ratePlanDesc varchar;
discountRate double;
Now, my question is..does this qualify as a onetomany relationship?
Most of the examples that I am seeing on the net regarding onetomany, involves some sort of collections (e.g An Order has a list of products). And when represented in class is translated below, which I think is really a one to many case?
public class Order{
private List products;
}
But how about my case? I don't think that it is a onetomany or I am just mislead by the examples?
How can I do a hbm mapping for my two classes? In my case, I would create two class to represent the two tables, but I am not sure how the hbm.xml would look like for the two class.
Yes, it is a one to many relationship, in that one rate plan is associated with many insurance policies. In entity traversal, when you would go from the Policy, you would get one Plan object, and conversely, from a Plan object, you would get a list of Policy objects.
I have two classes Parent and Child.
class Child extends Parent {
private String extraField1;
private String extraField2;
...
}
Child class has 2 extra fields extraField1 and extraField2.
Q1. Should I make two diff. tables in the databse: one for Child and other for Parent?
or
Q1. Should I add two columns in the Parent table (each column for one extra field) and store the Child in the Parent table.
=============================== EDITED =======================================
Yes, Child and Parent are classes in the same hierarchy.
Should there be 2 datatables for a Parent and Child class in Java?
There is no universal answer to this question. There are actually several techniques to map an inheritance hierarchy into a relational database and they all have advantages and disadvantages. Choosing one or the other depends on your context.
Scott Ambler details the various approaches in the section 2. Mapping Inheritance Structures of his famous paper Mapping Objects to Relational Databases: O/R Mapping In Detail that I'm quoting below:
(...) In this
section you’ll see that there are
three primary solutions for mapping
inheritance into a relational
database, and a fourth supplementary
technique that goes beyond inheritance
mapping. These techniques are:
Map the entire class hierarchy to a single table
Map each concrete class to its own table
Map each class to its own table
Map the classes into a generic table structure
For a full comparison (with advantages, disadvantages and a recommendation on when to use), have a look at the section 2.6 Comparing The Strategies.
I can't do a better job than him so there is no point at paraphrasing him, just refer to the original paper.
Patterns of Enterprice Application Architecture covers this as well in its chapters on Single-table inheritance, Class-table inheritance, and Concrete-table inheritance.
The coverage is similar to what Pascal has said. There's no One True Way, but the book does give you a good breakdown of costs and benefits, e.g.
The strengths of Concrete Table Inheritance are:
Each table is self-contained and has no irrelevant fields. As a result
it makes good sense when used by other
applications that aren't using the
objects.
There are no joins to do when reading the data from the concrete
mappers.
Each table is accessed only when that class is accessed, which can
spread the access load.
The weaknesses of Concrete Table Inheritance are:
Primary keys can be difficult to handle.
You can't enforce database relationships to abstract classes.
If the fields on the domain classes are pushed up or down the hierarchy,
you have to alter the table
definitions. You don't have to do as
much alteration as with Class Table
Inheritance (285), but you can't
ignore this as you can with Single
Table Inheritance (278).
If a superclass field changes, you need to change each table that has
this field because the superclass
fields are duplicated across the
tables.
A find on the superclass forces you to check all the tables, which leads
to multiple database accesses (or a
weird join).