I have 3 tables like this in MySQL 5:
| PERSON |
| id | fullName | isEmp | isParent |
| EMPLOYEE |
| personId | code |
| PARENT |
| personId | job |
in which, Employee.personId and Parent.personId are foreign keys pointing to Person.id. An employee can also be a parent and vice versa. So how can I config using Annotation of JPA 2.0/Hibernate 3? Thanks!
If a Person can be both, you can't solve this through inheritance, because Java doesn't allow multiple inheritance. So you'll have to go with Aggregation, which is confusing on a semantic level, because it's has-a-parent instead of is-a-parent. But I'm afraid it's the way you'll have to go:
#Entity
public class Person{
#Id
private Long id;
#OneToOne(optional=true)
private Employee employee;
#OneToOne(optional=true)
private Parent parent;
public boolean isParent(){return parent!=null;}
public boolean isEmployee(){return employee!=null;}
}
#Entity
public class Employee{
#Id
private Long id;
#OneToOne(mappedBy="employee",optional=false)
private Person person;
}
#Entity
public class Parent{
#Id
private Long id;
#OneToOne(mappedBy="parent",optional=false)
private Person person;
}
(getters / setters etc. omitted)
Related
I transform my site to use Java EE and hibernate!
I have 3 tables:
like
id | table | idElement | userId
movie
movie_id | title | duration
videoGame
game_id | title | nbPlayer
and currently 2 class:
#Entity
#Table(name="movie")
public class Movie {
#Id
#GeneratedValue
#Column(name="movie_id")
private Integer id;
private String title;
private int duration;
#Entity
#Table(name="videoGame")
public class Game {
#Id
#GeneratedValue
#Column(name="game_id")
private Integer id;
private String title;
private int nbPlayer;
I do not know how to make my table "like" to link it to one of the two table and the correct id?
example:
table like:
+---+-------+-----------+-------+
|id | table | idElement | userId|
|1 | movie | 1 | 1 |
|1 | game | 5 | 3 |
+---+-------+-----------+-------+
thanks a lot for your help!
Looks like there is no direct way to map your tables to hibernate (At least I am not aware of).
Using inheritance you can produce a similar effect. Movie and Game can be a subclass of another class (say Likable). So that you can use Likable class like below:
#Entity
#Table(name="like")
public class Like {
#Id
#GeneratedValue
#Column(name="like_id")
private Integer id;
#ManyToOne
#JoinColumn(name="likable_id", nullable=false)
private Likable likable;
#ManyToOne
#JoinColumn(name="user_id", nullable=false)
private User user;
}
Likable class will look like below:
#Entity
#Table(name = "likable")
#Inheritance(strategy=InheritanceType.JOINED)
public class Likable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private int id;
}
Movie class:
#Entity
#Table(name="movie")
#PrimaryKeyJoinColumn(name="id")
public class Movie extends Likable {
private String title;
private int duration;
}
And Game class:
#Entity
#Table(name="videoGame")
#PrimaryKeyJoinColumn(name="id")
public class Game extends Likable {
private String title;
private int nbPlayer;
}
I'm trying to find a solution for a this problem:
We have a table (code_list) in the database which contains all enum -like data.
Let us say we have an Affiliate that can have an AffiliateType and a LanguageCode.
We put all this in the code_list table where id_code_list field tells us if we are talking about AffiliateType or Languagecode and we can have a String or Integer identifier that tells us about which AffiliateType we are talking.
Example of the data in table:
| id_code_list | val_num | val_string | label |
| :----------: |:------: |:---------: | :-----:|
| TYP_AFF | 3 | 3 | Other |
| TYP_AFF | 1 | 1 | Divers |
| COD_LAN | 1 | 1 | French |
I tried to map this that way:
Code List Parent
#Entity
#Table(name = "CODE_LIST")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "ID_CODE_LIST")
public abstract class CodeListString {
#Id
#Column(name = "VAL_STRING")
protected String value;
#Embedded
protected Label label;
...
Affiliate Type:
#Entity
#DiscriminatorValue("TYP_AFF")
public class AffiliateType extends CodeListString{
public static final AffiliateType SOCIAL_SECRETARIAT = new AffiliateType("1");
public static final AffiliateType VARIOUS_SERVICES = new AffiliateType("2");
public static final AffiliateType OTHERS = new AffiliateType("3");
public static final AffiliateType SOPA = new AffiliateType("9");
public AffiliateType() {}
private AffiliateType(String value) {
super(value);
}
}
And my Affiliate entity:
#Entity
#Table(name = "AFF")
public class Affiliate {
#ManyToOne
#JoinColumn(name = "TYP_AFF")
private AffiliateType type;
But I'm getting this error:
org.hibernate.MappingException: Foreign key (FK7re97tvvbbo2km961gy9b5jw6:aff [typ_aff])) must have same number of columns as the referenced primary key (code_list [val_string,id_code_list])
So, is there a way to make this work or do you have other solution for this problem ?
PS: I'm using Hibernate and the solution like
#ManyToOne(targetEntity = AffiliateType.class)
#JoinColumn(name = "TYP_AFF")
#Where(clause = "ID_CODE_LIST='TYP_AFF'")
private AffiliateType type;
Doesn't work...
I've removed a dependency to a custom library and this worked.
I could not reproduce this error on a clean project.
Anyway this solution is really slow !
I got two classes. A class named person and a class named group. Now I created a view linking these classes and created a class with an #Immutual annotation.
View result
| person_id | group_id |
| ----------|----------|
| 1 | 2 |
| 2 | 2 |
| 3 | 4 |
| ... | ... |
Class PersonGroup
#Entity
#Table(name = "person_group")
#Immutable
public class PersonGroup {
#Id
#Column
private Person person;
#Column
private Group group;
public Person getPerson() {
return this.person;
}
public Group getGroup() {
return this.group;
}
}
Now i want to map PersonGroup to Person and Group. Like this:
Class Person
#Entity
public class Person {
...
private PersonGroup group;
...
}
Class Group
#Entity
public class Group {
...
private Set<PersonGroup> person;
...
}
Is that possible? If yes, which annotations should I use? I tried a lot and nothing worked for me.
Regards,
Xy
If you want to use PersonGroup in the Person Model then u have to use #Embeddable annotations to embed a value type object into our Entity class.
Like This :-
#Entity
#Embeddable
#Table(name = "person_group")
#Immutable
public class PersonGroup {
.....
then add anotation #Embedded to the Person Class.
Like this :-
#Entity
public class Person {
...
#Embedded
private PersonGroup group;
If you want to use the PersonGroup meodel in GroupModel Then use the #ElementCollection Annotationin Group Class as Below
#Entity
public class Person {
...
#ElementCollection
private Set<PersonGroup> person;
Please refer to the below tutorial.
Doc1 and Doc2
I have an entity class which contains a map. The map references ranked entities of type Child.
#Entity
public class Parent implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToMany
#JoinTable
private Map<String, Child> ranking;
}
#Entity
public class Child implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
}
I put objects into the map like so:
ranking.put(1, childA);
ranking.put(2, childB);
ranking.put(3, childA);
The Child class does not reference Parent. The map key is a ranking attribute I want to persist. I do not want the ranking attribute to be part of the Child class.
I want to achieve a join table (parent_child) where the columns look like:
|-------------| |----------| |---------------|
| parent | | child | | parent_child |
|-------------| |----------| |---------------|
| id | | id | | parent_id |
| ... | | ... | | child_id |
| | | | | ranking | <-- missing
|-------------| |----------| |---------------|
Actually, I do not get the rank column.
What am I missing? Is this even possible?
As hinted at above, you would need to create an additional Entity, say Relationship. You could then map this as Map like:
#Entity
public class Parent implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToMany(mappedBy ="parent")
#JoinColumn(name = "parent_id")
#MapKeyColumn(name = "ranking")
private Map<String, Relationship> ranking;
}
You shouldn't use map in your case, for this problem you should create an entity for your parent_child and create #NamedQuery to return the rank with children
In my db I have something similar:
+---------+
| answer |
+---------+ ----------------------->--+--------------+
| id +------) | answer_type_b|
---->-+--------------+ +--------------+
... | answer_type_a| | id |
+--------------+ | field_b |
| id | | ... |
| field_a |
| ... |
In my answer table I have common information, then I have two inheriting tables related to the parent table and having different specific fields.
I created model in my application using JPA 2 + Hibernate 4.2.6:
#Entity
public abstract class Answer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// ...
}
#Entity
public class AnswerA extends Answer{
#Column(name = "field_a")
private String fieldA;
// ...
}
#Entity
public class AnswerB extends Answer{
#Column(name = "field_b")
private String fieldB;
// ...
}
Now when I try to query all Answer entities I expect to get a collection with ALL the answers both Type A and Type B, instead I get an exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'answer0_.field_a' in 'field list'
I suppose this appens because there is no field_a field in parent table, so how can I solve this? Is there a way to query all the inheriting tables?
I solved following this interesting wiki-book.