Can I reference 2 different entities with same column in hibernate? - java

In my database, I have a column called "specialist_id". Based on the value of another column in the same table, it is either the id of a user entity (references some user table), or it is the id of a specialist entity (references specialist table). My question is, how can I do this in hibernate mapping? For example, I want to do something like below.....Is it possible?
#ManyToOne(fetch = FetchType.LAZY)
#Fetch (FetchMode.SELECT)
#JoinColumn(name = "SPECIALIST_ID")
private ApplicationUser specialist;
#ManyToOne(fetch = FetchType.LAZY)
#Fetch (FetchMode.SELECT)
#JoinColumn(name = "SPECIALIST_ID")
private DivSpecialist divSpecialist;

Related

How to create a separate table with two mapped fields?

I have a user entity. The user will have a list of friends. I have a problem with creating a batch to this mapped list. I want the board to look like this https://zapodaj.net/41cd4553308d3.png.html The first column is the user ID, and the second column is the friend's ID. I was thinking about doing it
#ElementCollection
#CollectionTable(
name = "users_friends",
joinColumns = #JoinColumn(name = "user_id", nullable = false, updatable = false)
)
#Column(name = "user_friend_id")
private Set<UserEntity> friends;
But ElementCollection does not map the entity and this way goes away.
How can I create such a special table for mapping the user with a list of friends?
This is a many-to-many relationship. JPA supports them no problem https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
In your case doing
#ManyToMany
#JoinTable(
name="users_friends",
joinColumns=#JoinColumn(name="user_id", referencedColumnName="id"),
inverseJoinColumns=#JoinColumn(name="user_friend_id", referencedColumnName="id"))
private List<UserEntity> friends;
Should do the trick

Hibernate mapping, entity with many to many relationship table

I got a many to many relationship between two tables. I mapping this using the annotation #ManyToMany.
Table1 ---> Relational Table ---> Table 2
Using hibernate i don't have to create any entity for the relationship table so I have.
Entity 1(Table 1) ---> Entity 2(Table 2)
But my problem is that i have another table and i must do a relationship between this 3th table and the relation table between the previous and i don't have any entity for do the relation.
Table 3 ---> Relational Table
I mean this 3th table got a foreign key with the relational table that i used before...
How can i accomplishment this? Sorry for my english
Thanks
here is an example.
Imagine we have Products and Categories
You have 2 entities Product and Category
Using the hibernate code-first approach, the entities will be like this:
#Entity
#Table(name = "products")
public class Product implements Serializable {
private Long id;
....
#ManyToMany
#JoinTable(name = "categories_products",
joinColumns = #JoinColumn(name = "category_id",
referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "product_id",
referencedColumnName = "id"))
private Set<Category> categories;
...
And here is the code for the code
public class Category {
private Long id;
private String name;
...
}
By using the annotation #JoinTable a third table will be created with the following constraints. It will have category_id which will point to Categories id and product_id referring to Products id.

How to model in JPA a "default selection" from a One-to-Many Relationship

I have a data model in which a Person may be known by one or more Names (such as the case of a woman who has changed her name after marriage). The model distinguishes the single Name that is being actively used.
The general relationship between Person and Name is modeled as usual: a bidirectional #OneToMany relationship in the Person entity and the corresponding #ManyToOne relationship in the Name entity classes.
To specify the "active or primary name" I have thought that I could model this as a unidirectional #OneToOne relationship from Person to Name. The mappings in the entity classes would look like this:
public class Person {
#Id #GeneratedValue(strategy = GenerationType.Identity)
private Long pers_id;
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "name_id", nullable = false)
private Name uniPrimaryName;
:
:
#OneToMany(mappedBy = "owningSidePerson", fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
private List<Name> mappedSideNames;
:
:
}
And the Name entity class:
public class Name
#Id #GeneratedValue(strategy = GenerationType.Identity)
private Long name_id;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinTable (name = "XREF_NAMES_PERSON",
joinColumns = #JoinColumn(name = "name_id", nullable = false),
inverseJoinColumns = #JoinColumn(name = "pers_id", nullable = false))
private Person owningSidePerson;
:
:
}
The advantage of this model is that it lets me access the primary Name as a simple property access from Person. It should also be easier to maintain. The downside relates to serializing Person entities that have circular references, but this problem is present whether the unidirectional relationship is present or not.
An alternative model would be to add an active boolean attribute to the Name entity and use it to indicate which entity in the relationship was the active one. The downsides are that maintaining the attribute would be less straightforward and obtaining the active Name would require a separate database query.
Before I invested time in this design, I wanted to ask if anyone has tried this before. I have concerns about an object model which uses an entity object that would be present in a unidirectional and a bidirectional relationship at the same time.
My suggestion is to just leave the person's relationship to name (mappedSideNames) and delete the relationship mapped by uniPrimaryName attribute to identify whether the name is primary or not u can create a named query for this purpose, but you will have to create a way to differentiate the primary names as you quoted by setting a flag.

merge in jpa many-to-many with extra column in join table

I have a many-to-many relationship with three tables and entities adn the join table contains additional column. On both sides of the relationship I have set cascadeType.All
When I add new objects to owner side the merge method works fine but when I remove a child object from the owner and merge it, the corresponding rows in the join table will not be removed and I will have duplicate rows in there.
owner entity
#OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "definitionType")
private List<DefinitionProperty> definitionProperties = new ArrayList<DefinitionProperty>();
#OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "property")
private List<DefinitionProperty> definitionProperties= new ArrayList<DefinitionProperty>();
mapping entity
#Id
#JoinColumn(name = "dtid", referencedColumnName = "id")
#ManyToOne(optional = false)
private DefinitionType definitionType;
#Id
#JoinColumn(name = "prid", referencedColumnName = "id")
#ManyToOne(optional = false)
private Property property;
I am not calling remove method of my entity manager at all and I am expecting the cascading to remove the unwanted rows automatically. Is that possible? what should I do to in order to remove those rows?
I can add my code here if it help
It just needed orphanRemoval=true on the owner side.

How to generate some JPA entities with a multi join?

i would like to create an application in this context : Zk 6, Spring v3.1.1, JPA 2.0, Hibernate 4.1.4, all with annotations but i have some pb with JPA concept.
Here are a type of case study :
3 tables, all linked via a join table ; we are dealing with cardinality 0, n.
So we have T_E_USER, T_E_TYPE and T_E_AIR.
Each table has a numeric ID, and a simple VARCHAR field.
A join table is created with T_J_USR_TPE_AIR with the 3 ID referenced by foreign keys forming a composed primary key.
I'm using Hibernate Tools for generate my entities (version JPA).
And that's where the problems start ....
I have, in each entity class, an attribute of type set with annotation # OneToMany.
I have a class representing the join that has an id attribute of complex type (another class) with an annotation EmbeddedId for a composite key.
And attributes representing the three entities with annotations # ManyToOne.
Here are my questions, because that's where I'm confused:
which should i set into the "mappedBy" attribute in the annotation # OneToMany of my entities?
Am I forced to do a class entity representing the join?
How does the CASCADE? Is it possible to use it in this context to enrich the join table "automatically"? Or should I manually instantiate the class representative of the join in order to persist the information myself?
A big thank you in advance for any kind soul who could give me a helping hand.
Thank you for your answers but one said "yes" when the other says "no" lol
Here's what I did during the day but I have not yet been tested.
In each entity table, i added a #OneToMany relation with mappedBy setted to the attribute defined in "join" entity :
#OneToMany(fetch = FetchType.LAZY,
mappedBy = "aircraft",
cascade = { CascadeType.REMOVE })
private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0);
...
#OneToMany(fetch = FetchType.LAZY,
mappedBy = "userAccount",
cascade = { CascadeType.REMOVE })
private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0);
...
#OneToMany(fetch = FetchType.LAZY,
mappedBy = "referenceType",
cascade = { CascadeType.REMOVE })
private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0);
And i created a new Entity for the join table.
#Entity
#Table(name = "T_J_USR_RFT_AIR_URA")
public class UserConfig implements java.io.Serializable {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "airId",
column = #Column(name = "URA_AIR_ID", nullable = false)),
#AttributeOverride(name = "usrId",
column = #Column(name = "URA_USR_ID", nullable = false)),
#AttributeOverride(name = "rftId",
column = #Column(name = "URA_RFT_ID", nullable = false))
})
private UserConfigId id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "URA_RFT_ID", nullable = false, insertable = false, updatable = false)
private ReferenceType referenceType;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "URA_USR_ID", nullable = false, insertable = false, updatable = false)
private UserAccount userAccount;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "URA_AIR_ID", nullable = false, insertable = false, updatable = false)
private Aircraft aircraft;
...
getter & setter
}
Where UserConfigId is :
#Embeddable
public class UserConfigId implements java.io.Serializable {
#Column(name = "URA_AIR_ID", nullable = false)
private Integer airId;
#Column(name = "URA_USR_ID", nullable = false)
private Integer usrId;
#Column(name = "URA_RFT_ID", nullable = false)
private Integer rftId;
...
getter & setter
}
What do you think about this practice ?
I just used "cascade" if an object of the join table is deleted in order to delete all element associated in the join.
Is it all right ?
Anyway thank you Tom, i will analyzed your link.
Thank you JMelnyk too.
You are welcome if you want to demonstrate what are the best practices for this case.
Three-way joins are tricky. I think what you've done, using an entity for the join table, is probably the right thing to do. To answer your questions:
Your #OneToMany attributes refer to the entity mapping the join table; they should be mappedBy the appropriate #ManyToOne attribute in that entity.
Yes, unfortunately, an entity for the join table is the best way to do this.
Cascades can be used to automatically add objects to the database, but not to create objects. You will need to create instances of the join entity in code.
which should i set into the "mappedBy" attribute in the annotation #
OneToMany of my entities?
mappedBy attribute represents a property name you are joining on. Read more...
e.g. AnyEntity holds List<Employee> which is joined on (mappedBy) department property in Employee entity, and that department property holds the association.
Am I forced to do a class entity representing the join?
No, you do not provide an entity class for join tables.
How does the CASCADE? Is it possible to use it in this context to
enrich the join table "automatically"? Or should I manually
instantiate the class representative of the join in order to persist
the information myself?
Yes it is possible to enrich associations of the entity and itself by marking associations with desired cascade type.
e.g. We have a Department which holds List<Employee> and I put CascadeType.PERSIST on employees. Now we populate department objects with its properties and employees. When we are finished, we persist only the department, and it will cascade operation to employees.

Categories