Under hibernate-jpa-api-2.0, can i specify the name of the foreign key using #PrimaryKeyJoinColumn with oneToOne relation ?
I tried the folowing but it doesn't seem to work.
#OneToOne(optional = false, fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn(name = "CARID")
#ForeignKey(name = "FK_CAR_CORP")
public CarEntity getCar() {
return car;
}
There are two #ForeignKey annotations can be used:
org.hibernate.annotations.ForeignKey (Hibernate annotation)
javax.persistence.ForeignKey (JPA annotation)
Hibernate 4 (even the last version) sometimes doesn't process, probably cause of bug, javax.persistence.ForeignKey annotation.
For example, with Hibernate 4.3.11 we should use org.hibernate.annotations.ForeignKey on the #OneToMany part of unidirectional association. And we can use javax.persistence.ForeignKey on the #ManyToOne part of bidirectional association.
So you can try to use Hibernate org.hibernate.annotations.ForeignKey annotation.
The mappedBy attribute is only necessary for a bidirectional relationship, this element can be omitted on the annotation. It is used on the source entity to point back to a field on the target entity that defines the relationship (contains #JoinColumn).
The #JoinColumn annotation should be placed upon the billSimpleEntry field to define the column that should be used to join the two tables. In the case of a OneToOne the following applies:
If the join is for a OneToOne or ManyToOne mapping using a foreign key mapping strategy, the foreign key column is in the table of the source entity or embeddable.
Here is a code example:
#OneToOne(cascade=CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name="id") // use actual column name
private ClassName className; // use class name
I don't think #ForeignKey will work for hibernate-jpa-api-2.0, as per doc it's release in 2.1
Since:
Java Persistence 2.1
here is doc
Related
I am trying to understand the javax.persistence annotations #OneToOne, #ManyToOne and #ManyToMany. The descriptions for these annotations make a mention of non-owning side. Specifically:
[#OneToOne]: If the relationship is bidirectional, the non-owning side must use the mappedBy element of the OneToOne annotation to specify the relationship field or property of the owning side.
[#ManyToOne]: If the relationship is bidirectional, the non-owning OneToMany entity side must used the mappedBy element to specify the relationship field or property of the entity that is the owner of the relationship.
[#ManyToMany]: If the relationship is bidirectional, the non-owning side must use the mappedBy element of the ManyToMany annotation to specify the relationship field or property of the owning side.
I am having trouble understanding this ownership aspect. For example, I have the following associations:
Note: Images taken from here.
So which are the non-owning entity sides of these associations?
In the bi-directional relationship betweens two objects ,you have to choose which sides to manage the relationship. From the database perspective , managing the relationship means managing the value of some FK column that link between two tables. The side that managing it is called owning side. Otherwise, it is call non-owning side.
So back to your example on ProjectManager and Project. Which object is the owning side depends on which object you choose to manage their relationship.
If you choose ProjectManager to be the owning side (hence Project is the non-owning side), only the values of ProjectManager#getProjects() will be used to determine the value of such FK column. (i.e. project table 's project_manager_id column in this case) The value of Project#getProjectManager() will be ignored and does not affect the value of this FK column.
In term of JPA mapping , it is :
#Entity
#Table(name="project_manager")
public class ProjectManager{
#OneToMany
private List<Project> projects = new ArrayList<>();
}
#Entity
#Table(name="project")
public class Project {
#ManyToOne
#JoinColumn(name = "project_manager_id")
private ProjectManager projectManager;
}
On the other hands , if you choose Project to the owning side (hence ProjectManager is the non-owning side) , only the value of Project#getProjectManager() will be used to determine the value of this FK column while the value of ProjectManager#getProjects() will be ignored. The JPA mapping in the case will be :
#Entity
#Table(name="project_manager")
public class ProjectManager{
#OneToMany(mappedBy="projectManager")
private List<Project> projects = new ArrayList<>();
}
#Entity
#Table(name="project")
public class Project {
#ManyToOne
#JoinColumn(name = "project_manager_id")
private ProjectManager projectManager;
}
P.S: I explain it using property access , hopefully you should get the idea.
I got error:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on xxx.yyy.zz.myentity.xxx_id references an unknown entity: java.util.UUID
code
#ManyToOne
#JoinColumn(name = "xxx_id", nullable = false, updatable = false, referencedColumnName = "xxx_id", insertable
= false)
private UUID xxxId;
I got this when i change from AnotherEntity to UUID. I did this because i dont want to hold an object in my entity but only key to it(key type in AnotherEntity is UUID). I found that this error is cause when Object isnt annotated with
#Entity annotation. Is it true? How can i fix this?
You can represent an Entity as a SQL table and fields (properties) from this Entity as the columns from this table.
That's the easiest way to use Hibernate (or any other JPA implementation).
When you define a relationship (OneToOne, OneToMany, ManyToOne or ManyToMany) you are linking SQL tables so, with JPA, you are linking Entities.
As you can imagine, you can't define a relationship between a table and a column.
So:
your xxxId is supposed to be an object (Entity/Table) mapped in your database and Hibernate must know the column mapping.
that's the purpose of the #Entity annotation and all #Column, #JoinColumn you can use on an Entity class.
so yes, you can't use an object in a ManyToOne relationship that is not annotated with #Entity (it would be considerate by Hibernate like a column)
therefore, you cannot use an object from the JDK (because they are not annotated with any JPA annotation)
more specifically, java.util.UUID is not a class you can change. so you have no way to tell hibernate how it can map it to a Table in your DB.
so the only way I can imagine in your case is to use an entity you created to wrappe the UUID. For example:
#Entity
#Table(name="UUID")
public class UUIDWrapperEntity {
#Id
#Column(name = "UUID")
private UUID uuid;
}
I'm using hibernate 3.2.1.
In an entity class I've seen the annotations #OneToMany and #JoinColumns are always used together. But what do these mean in separate? For instance what it would mean if we annotated our entity class as follows:
#Entity
#Table(name = "player_account")
public class PlayerAccount {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#ManyToOne(targetEntity = Player.class, fetch = FetchType.EAGER)
//Without #JoinColumn
private Player player;
//GET, SET
}
Please see what says Hibernate documentation about it: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
You need 2.2.5.2. Many-to-one section:
The #JoinColumn attribute is optional, the default value(s) is like in one to one, the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column in the owned side.
#OneToMany annotation defines a many-valued association with one-to-many multiplicity.
If the collection is defined using generics to specify the element type, the associated target entity type need not be specified; otherwise the target entity class must be specified
#JoinColumn is used to specify a mapped column for joining an entity association.
I have a question about Hibernate ManyToMany mappings. I have two classes A and B and the mapping between them is a ManyToMany mapping resolved by Hibernate:
#Entity
#Table(name="A")
public class A {
#Id
#GeneratedValue
private Long id;
#ManyToMany
#JoinTable(name="C", joinColumns=#JoinColumn(name="a_id"), inverseJoinColumns=#JoinColumn(name="b_id"))
private Set bs;
}
#Entity
#Table(name="B")
public class B {
#Id
#GeneratedValue
private Long id;
#ManyToMany(mappedBy="bs")
private Set bs;
}
As you can see, the Join Table I use is C. The foreign keys to A and B are "a_id" and "b_id". My understanding is, that Hibernate creates a composed Primary Key with a_id and b_id for table C.
I don't want to have an entity C in my model. But instead of a composed primary key on table C, I would like to have a generated ID and a unique constraint on the fields a_id and b_id.
Is it possible to tell Hibernate to use a separate primary key? Without adding an entity C?
I would appreciate any help.
Thanks a lot!
You should do iyt like this. But it can be appled only for list (not for sets)
#Entity
#TableGenerator(name="ids_generator", table="IDS")
public class Passport {
...
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="PASSPORT_VISASTAMP")
#CollectionId(
columns = #Column(name="COLLECTION_ID"),
type=#Type(type="long"),
generator = "ids_generator"
)
private Collection<Stamp> visaStamp = new ArrayList();
...
}
I don't think it is possible. And I don't see a problem in defining a C entity.
If you have any additional information ind the join-table, it will not be accessible to you, because your Set contains the target entity - A or B.
Also, your Sets would better make use of generics - i.e. Set<A> and Set<B>.
Btw, Hibernate might not be alarmed by the fact that the table creates another entity - using your current mapping might work (disregarding completely the id column). When you said "Hibernate creates", I assumed you are generating your schema from your entity model. Now it seems it's the opposite, so give it a try.
But instead of a composed primary key on table C, I would like to have a generated ID and a unique constraint on the fields a_id and b_id.
Normally the primary key of the JoinTable is made of the combination of both foreign keys. At least, this is what JPA would generate. But if you don't use the JPA provider to generate the model and if the PK can be generated by the database (using an IDENTITY column, a trigger, etc), then you should be able to use the C table for your ManyToMany association (without having to introduce an extra entity and to transform the relation in two OneToMany). Did you actually try?
I have entity classes A and C. They are mapping the tables tblA and tblC and have a many-to-many relationship between them, with tblB to map between them. tblB contains A_ID, C_ID and SetDate, the last one being the date it was set, thus an attribute to the relationship. My question is, how do I best map in this attribute? At the moment they're unmapped, like this:
A:
#ManyToMany(targetEntity=C.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE } )
#JoinTable(name="tblB", joinColumns=#JoinColumn(name="A_ID"), inverseJoinColumns=#JoinColumn(name="C_ID") )
private Collection<C> Cs;
C:
#ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "Cs", targetEntity = A.class )
private Collection<A> As;
How should I get tblB.SetDate out of this?
Cheers
Nik
From what I know, it is not possible to map it this way, you have to switch to One-To-Many and a Many-To-One relationships, with your B in the middle. Your date will be an attribute of B.
For this lack of evolutivity, the Hibernate documentation recommends to avoid the Many-To-Many in general, and use the two relationships from the beginning.
See
#ManyToMany Hibernate Question (can add extra field?)
And
how to make a composite primary key (java persistence annotation)
regards,