I am trying to understand what would be the better way to design 2 entities which has many-to-many relationship? In database there will be a connecting table between these two entities. But do i have to follow the same approach while creating my entities?
For example: User to User group
A user may belong to many group and a group may contain many user.
In relational database I will have 3 table like User, User2Group, Group
So when I am creating my JPA entities, should I have 3 entities for 3 table or just 2 entities by providing the proper annotation(#ManytoMany).
Since I am new to JPA, I am trying to understand good and bad side from following point of view:
Performance
Code maintenance
Thanks, you input will be greatly appreciated.
No, you don't need to map the join table as an entity. Just use the ManyToMany annotation:
public class User {
...
#ManyToMany
private Set<Group> groups;
}
public class Group {
...
#ManyToMany(mappedBy = "groups")
private Set<User> users;
}
You would only need to map the join table as an entity if it was not a pure join table, i.e. if it had additional information like, for example, the date when the user entered in the group.
The mapping has little incidence on the performance. What is important is how you use and query the entities, and how the database is designed (indices, etc.)
Related
I am pretty new to EclipseLink.
Iwould like to know :
is it possible to create entities from 2 differents databases ? if yes, how ? (example please)
let's say I have Database1 and Database2, is it possible to create composite unit whose one field of entity 1 from database 1 is an entity 2 from database 2. if yes, how (example please)
Thank you very much
Assuming two different schemas on the same server, you should be able to do this using the #SecondaryTable annotation which allows you to map one entity to 2 or more tables. The annotation allows you to specify to the schema or catalog containing the secondary table.
https://docs.oracle.com/javaee/5/api/index.html?javax/persistence/SecondaryTable.html
Would look something like:
#Entity
#Table(name = "main_table")
#SecondaryTable(name="secondary_table", schema="secondary_schema")
public class MyEntity{
#Column(name = "my_field", table="secondary_table")
private String fieldFromSecondaryTable;
}
If you are talking about two different servers then you can look at doing something at the database level which would allow you to create a DB view and then map an entity to this view. This would work for read operations but not sure about writing...
In SQL Server, for example, you would be looking at creating a Linked Server:
Selecting data from two different servers in SQL Server
I am a beginner to using JPA 2.0 and databases in general and I was just confused about a few concepts.
So I have a total of 3 tables. One is the UserTable, which contains all the information about my user. It has a primary key field called user_Id. My other two tables are ExercisesTable and FoodIntakeTable, and they each have a foreign key field called user_Id to reference the user_Id in my UserTable. I want a one-to-many relationship from my user_Id table to each of the two tables so I can find pull out exercise information or food information for a user.
Pretty much like this:
FoodIntakeTable <-> UserTable <-> ExercisesTable
I need a bidirectional mapping from UserTable to FoodIntakeTable and also a bidirectional mapping from UserTable to ExercisesTable from the field user_Id.
The problem is, when I try to write my code like this in my Usertable class:
#OneToMany(mappedBy="ExercisesTable.userId")
#OneToMany(mappedBy="FoodIntakeTable.userId")
public long userId;
It's illegal because I can't have two #OneToMany annotations on the same field. I think it's supposed to be legal in a normal relational database and I'm just confused about how you translate this into JPA. I'm very new to the whole concept of databases and entities in general, so any help would be appreciated.
In JPA you can directly reference entity objects instead of the ids that they are mapped by. Try something like this:
You should have an entity type for each of your tables, say Exercise for ExercisesTable, FoodIntake for FoodIntakeTable, and User for your UserTable.
Then your User entity is the owning side of the relationships, having one field per relationship like this:
#OneToMany(mappedBy=...)
private List<Exercise> exercises;
#OneToMany(mappedBy=...)
private List<FoodIntake> foodIntakes;
I am working with Eclipselink and having issue with using secondary table.
I have two tables as below.
Student with columns student_id(Primary Key), student_name etc.
Registration with columns student_id(FK relationship with Student table), course_name (with not null constraint) etc.
The requirement is student may or may not have registration. If student has registration, the data should be persisted to Registration table as well. Otherwise only Student table should be persisted.
My code snippet is as below.
Student.java
------------
#Entity
#Table(name = "STUDENT")
#SecondaryTable(name = "REGISTRATION")
#Id
#Column(name = "STUDENT_ID")
private long studentId;
#Basic(optional=true)
#Column(name = "COURSE_NAME", table = "REGISTRATION")
private String courseName;
I tried the following scenarios.
1. Student with registration - Working fine. Data is added to both Student and Registration tables
2. Student without registration - Getting error such as 'COURSE_NAME' cannot be null.
Is there a way to prevent persisting into secondary table?
Any help is much appreciated.
Thanks!!!
As #Eelke states, the best solution is to define two classes and a OneToOne relationship.
Potentially you could also use inheritance, having a Student and a RegisteredStudent that adds the additional table. But the relationship is a much better design.
It‘s possible using a DescriptorEventListener. The aboutToInsert and aboutToUpdate callbacks have access to the DatabaseCalls and may even remove the statements hitting the secondary table.
Register the DescriptorEventListener with the ClassDescriptor of the entity. For registration use a DescriptorCustomizer specified in a Customizer annotation at the entity.
However, you will not succeed fetching the entities back again later on. EclipseLink uses inner joins when selecting from the secondary table, so that the row of the primary table will be gone in the results.
so the story is very simple.
I have one table called Products and another Called categories. In addition, i have another table called ProductCategories that hold the relationship of catetories to their corresponding products (i.e, the table has two columns, ProductId, ColumnId).
For some reason, after adding all those table to my entity model, i don't have "Access" to it, hence i can do myentityModel.ProductCategories, so i could relational items between those two tables.
And yes, the ProductCategores table is added as "Association" to the entity model. i don't really understand that.
EDIT:
I do see that as part of creating new "Product" i can pass EntityCollection of "Category". So i do query from my entity model for a list of the matching categories that the user selected (on the webpage). so for example, i get (after query the model), an Objectset of "Category". However, i encountered two issues:
the 'AddObject' accept only EntityCollection, hence i need to re-create a set and then add all the objects from the ObjectSet to the entityCollection, in this process i need to detach it from the previous model and add it to the new collection. if not, i get an exception.
when i do the SaveChanges, i see that i get an exception that it was actually trying to Create new Category rather than adding new ProductCategory. again, am i missing something here?
Thanks.
This sounds like a Many-to-Many relationship. In your entity model, you don't need to declare the join table as a separate entity. Instead, you configure the relationship between the Products and the Categories as a Many-to-Many and add metadata about the join table. In Hibernate, you would have:
#ManyToMany(targetEntity=Categories.class, cascade={CascadeType.ALL}, fetch = FetchType.LAZY)
#JoinTable(name="tb_products_categories",
joinColumns=#JoinColumn(name="category_id"),
inverseJoinColumns=#JoinColumn(name="product_id")
)
#IndexColumn(name="join_id")
public List<Categories> getCategories() {
return categories;
}
When you query, the ORM layer takes care of determining SQL and traversing table joins.
I have the following database tables:
Table1: UserUserIdUsername
Table2: RoleRoleIdRolename
Table3: UserRoleUserIdRoleId
A User can have many Roles and a Role can have many Users.
When I model this with EF, I get a User entity with a list of UserRole entities. What I want is a User with a list of Role entities.
Is there a way to model this or query via LINQ to return a User entity and the Role entities they belong to?
Thanks
Dirk
If you model a many-to-many relation, the table in the middle will not appear in your conceptual model. (i.e. you will not have a class "UserRole" derived from "EntityObject")
If you use the EF wizard, ensure that your table "UserRole" only have these two Fields and no others. Also ensure, that you have created the foreign key constraints on both of the fields. if you have, then the wizard will create a proper many-to-many relation.
The query then probably looks something like
using(MyObjectContext context = new MyObjectContext(someParameters)){
var theUser = (from user in context.UserSet
where user.UserId = XY
select user).First();
theUser.Roles.Load();
}