OneToMany and JoinColumn annotations is separate - java

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.

Related

JPA: How do I set up an entity with several children and several parents of same entity type?

I'm trying to model a business entity, where said business can have several parent businesses and several child businesses. I'm not sure which relationships are suited, or even what mapping is appropriate. I'm familiar with SQL but new to ORM in Java.
My thinking is that a business can have many or none children, and a business can have many or none parents. Therefore I've tried setting both as OneToMany but also as OneToMany, both resulting in this error: Illegal use of mappedBy on both sides of the relationship.
The implementation:
#Entity
public class Business{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "parentOrgs")
private Collection<Business> chlidOrgs;
#OneToMany(mappedBy = "chlidOrgs")
private Collection<Business> parentOrgs;
// --- Getters and setters below ---
What am I not understanding here? Any and all help much appreciated.
Your current mapping is syntactically incorrect, because only one side of the relationship can be owning side. Owning side is the field defined by value of mappedBy attribute. More detailed explanation can be found from here.
Also removing mappedBy from the one side does not solve the problem, because counterpart of OneToMany must be ManyToOne. Removing it from the both sides leaves us with two unirectional associations, which is also not what is needed.
Because each Business can have multiple parents and it seems to be preferred to be able to navigate directly to the childrens as well, solution is to use bidirectional ManyToMany:
#Entity
public class Business {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToMany(mappedBy = "parents")
private Collection<Business> childrens;
#ManyToMany
private Collection<Business> parents;
}
From database point of view this means following tables:
Business(id)
Business_Business(childrens_id, parents_id)
When necessary, name of the join table and columns can be controlled via JoinTable.

UUID as foriegn key in #ManyToOne hibernate

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;
}

#PrimaryKeyJoinColumn with name of foreign key

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

Storing data using hibernate for inter related tables

I have two tables (say table A and table B). Table B has foreign key from table A primary key. I generated my java entities using netbeans IDE and i now have something like:
For table A:
#Entity
#Table(name = "WORKFLOW_TRANSACTION")
public class WorkflowTransaction implements {
#OneToMany(mappedBy = "wtId")
private Collection<WorkflowTask> workflowTaskCollection;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "APP_ID")
private BigDecimal appId;
.
.
.
For table B:
#Entity
#Table(name = "WORKFLOW_TASK")
public class WorkflowTask implements Serializable {
#JoinColumn(name = "WT_ID", referencedColumnName = "APP_ID")
#ManyToOne
private WorkflowTransaction wtId;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "TASK_ID")
private BigDecimal taskId;
#Column(name = "STEP_NUM")
private BigInteger stepNum;
.
.
.
Now my questions are:
What is the correct way to save data, should I create object for table B entity and set it in table A entity and then save table A?
I am generating entity beans using netbeans IDE feature. Are there any known disadvantages of it?, if yes, what?
You have bi-directional association, so you need to setTable B property in Table A entity class and also vice-versa. Since you have not declared cascading, you need to save the Table A entity first and then Table B entity.
Alternatively, if you save Table B and then Table A entity classes, the hibernate generates an extra SQL update command to maintain the relationship.
But if you want hibernate to save Table B entity when you save Table A entity then you need to add Cascade property:
#OneToMany(mappedBy = "wtId", cascade=CascadeType.ALL)
I don't think you will have any disadvantages if you use Netbeans for generating the entity classes, it save you time in writing the entities. But if you want to learn then writing entities without Netbeans is good.
To achieve this you can use two type of techniques XML mapping or Annotations
In both these techniques the common point is use
cascade="save-update"
What happens is that you set an attribute in one table getter and it will automatically insert into the many relation when inserting into one relation table

Prevent duplicate entry for unique constraint

I am trying to save tags which are related to an article in my MySQL database. The relation between those two columns is 1:N. Each item has an auto generated key. The name of a tag is unique.
If I insert a new article with an existing tag, I get a duplicate entry exception for the unique constraint (MySQLIntegrityConstraintViolationException). This are my two entities:
Article.java
#Entity
public class Article implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable
private Set<Tag> tags = new HashSet<Tag>();
/* getter and setter */
}
Tag.java
#Entity
public class Tag implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true)
private String name;
/* getter and setter */
}
Hibernate generate following tables: article, tag, article_tag. For the first article the records are correct.
I use following code to insert a new article (only for testing):
Article article = new Article();
Tag tag = new Tag();
/* set the values */
EntityManager em = EMF.getInstance().get();
em.getTransaction().begin();
em.merge(article);
em.getTransaction().commit();
How could I get JPA to use the existing tag for the article instead of create a new one. How do I set the relation between those so components correctly?
In general the relationship between articles and tags is a many-to-many relationship as an article may have many tags and each of these tags may be reused in many articles.
To indicate a many-to-many relationship the #ManyToMany annotation is required.
Also to make something clear, in the OP it is indicated a unidirectionaly one-to-many relationship as the #JoinTable annotation has been used on the many side. This is the reason a join table has been created. In addition as a consequence if a #ManyToOne annotation is used in Tag class the many-to-one will be another unidirectional relationship. Just be careful there as they will be handled as two independent unidirectional relationship with probable strange behaviour and any configuration will not affect both entities, since it is not a biderictional relationship.
Finally, if it is required to have a one-to-many unidirectional relationship but also reuse the tags, it is required to retrieve them based on their name, so that they have the correct record id and then set the to the Article instance. If you try to set a new instance of Tag which will have no record id but a name that already exists, then the jpa provider will try to insert the new tag and a unique constraint exception will be thrown, because of the duplicate tag name. Also will need to remove any unique constraint referred to tag_id in article_tag table.

Categories

Resources