Hibernate-OneToMany mapping for existing DB Tables - java

I am trying to join to Hibernate Entities in a OneToOne Mapping. I am able to fetch the data for a given primary key from the Main Entity, the joining entity, however, returns null. I am new to hibernate and any help will be appreciated.
I have two Tables,
PT_CORE
Primary Key: ptId - Integer;
Foreign Key: stId(ST_AUX) - Integer;
Columns: ptId, ptName
ST_AUX
Primary Key: stId;
Columns: stId, stName
The two tables get populated by other applications and mine is a read-only operation.
Below is my first Entity class(PtCore.java)
#Entity
#Table(name="PT_CORE")
public class PtCore implements Serializable{
#Id
#Column(name="ptId", nullable = false)
private int id;
#Column(nullable=false)
private int stId; //The Foreign key column
#OneToOne
#JoinTable( name = "core_aux", joinColumns = {#JoinColumn(Name="ptId")},
inverseJoinColumns = {#JoinColumn(Name="stId")}
)
private StAux staux;
//Getters, setters and toString() for above
}
StAux is another Entity, defined as below,
#Entity
#Table(name="ST_AUX")
public class StAux implements Serializable {
#Id
#Column(nullable=false)
private Integer stId;
#OneToOne
private PtCore ptcore;
#Column
private String stName;
//Getters, Setters and toString follow.
}
I do below in the Service method:
PtCore obj = (PtCore) session.get(PtCore.class,1);
System.out.println(obj);
In the Results, I get the value of ptName, but the stAux class variables are null, Indicating that the join does not work as expected.

First of all you have the mapping information existing in your PT_CORE. And I assume it is something like FOREIGN KEY (stid) REFERENCES (stid). If you want to use existing schema and existing data I guess there is no mapping table core_aux really existing. At least you did not mention it. However it is visible as #JoinTable annotation but still there is this above mentioned foreign key which seems to be the real mapping (so again not the join table).
I suggest the following
remove this
#Column(nullable=false)
private int stId; //The Foreign key column
from your PtCore. I think it is not needed. Also in PtCore, remove the #JoinTable (because what I told above) and add mapping informaiion to #OneToOne annotation, like:
#OneToOne
#JoinColumn(name = "stid")
private StAux staux;
from your PT_CORE.
Then in StAux alter also a bit:
#Id
#Column(name = "stid") // this might not be needed but if there is like "st_id"...
private Integer stId; // so just for sure
#OneToOne(mappedBy = "staux")
private PtCore ptcore;
Because you have existing tables and constraints there might raise errors if hibernate tries to auto-generate those again by JPA instructions.
Check this for example for more information.
UPDATE: just realized also that in your title is #OneToMany but in your code is #OneToOne.
So you might want to elaborate your question and/or title a bit.

In your relation, the owning side is PtCore, the inverse side is StAux.
In bidirectional OneToOne relations, the inverse side has to have the mappedBy attribute. Actually, the mappedBy attribute contains the name of the association-field on the owning side.
So, you must change your inverse side code (StAux Entity). You have to add mappedBy attribute to #OneToOne in StAux class:
#OneToOne(mappedBy="staux")
private PtCore ptcore;

Related

How to create table with unidirectional relation in Hibernate?

i have the empty database in mysql, and two java entites. One of those have unidirectional relation. When hibernate tryes to create tables, i got the error:
Error executing DDL "alter table entry add constraint FK6ov2k83sx3crs9v3q8nvjuf1j foreign key (category_name) references category (name)" via JDBC Statement
There are my entites:
#Entity
public class Entry {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY)
private int id;
#Column
private String myfio;
private String descr;
#OneToOne(cascade = CascadeType.ALL)
private Category category;
}
And the second:
#Entity
#Table(name="category")
public class Category {
#Id
#Column
private String name;
}
How to create tables without errors?
OneToOne relationship shares the same id. So it should be the same type, but the first one is int (actually it should be Integer to allow null value for the transient (not stored) entities) and the second one is String. It seems you simply missed a line. Also, it worths to mention Vlad Mihalchea’s article https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

Foreign key as primary key annotation

There is 2 entity
Product(product_id(PK),product_name..)
Store(product_id(PK,FK),product_quantity,...)
I need #OneToOne, so i do this
public class Product{
#Id
#Column(name="PRODUCT_ID")
#OneToOne(mappedBy="product")
private int product_id;
....
}
public class Store{
#Id
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "PRODUCT_ID")
private Product product;
}
Compilier says #Column(s) not allowed on a #OneToOne property: ......shopdb.entity.Product.product_id
What is the problem?
I just moved #OneToOne(mappedBy="product") to new created field in Product
private Store store;
I dont understand how it works correct;
Why i need to use 3 fields instead of 2?
You can't mark a column defined with #JoinColumn as #Id. This is applicable only to columns defined with #Column annotation.
It is also a bit strange what are you trying to do. You are basically making the produc_id primary key for both entites, so then why don't make just one?
From what I can see here, I believe that the Store should have a store id property which will be used as primary key.

Hibernate - How to use a generator to create a primary key for a reference table?

I'am struggling to get Hibernate (with MySQL) to generate the primary key for a reference table from a "main table". My problem is that I got a big table with 25 mil rows and now I need to add multiple additional columns and because in the future where will be even more columns to add I choose the way to work with reference tables instead of adding the columns to the main table (the rebuild takes hours... :)
So there is a main table and a reference table. In my conception the primary key of the reference table should be generated from the primary key of the main table. I could first insert an entry into the main table, then select it and use its primary key for the insert into the reference table, but this seems not to be the best way to me. So I would like to use Hiibernate's generators, but I can't figure out how.
Here's the main table:
#Entity
#Table
public class Task {
#Id
#GeneratedValue
#Column()
private Integer id;
// ...
#OneToOne(mappedBy = "task_ref", orphanRemoval=true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Stuff stuff;
// ...
}
And the reference table:
#Entity
#Table
public class Stuff {
#Id
#Column(name = "stuff_id")
#GeneratedValue()
private Integer stuff_id;
// ...
#OneToOne(orphanRemoval=true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Task task_ref;
// ...
}
So.. how can I use a generator to create the primary key for the table Stuff from the primary key of the table Task ?
Any suggestions or other solutions are highly welcome!
Thanks!
This is how you should map your bidirectional OneToOne association with a shared primary key:
#Entity
#Table
public class Task {
#Id
#GeneratedValue
private Integer id;
// ...
#OneToOne(mappedBy = "task_ref", orphanRemoval=true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Stuff stuff;
// ...
}
#Entity
#Table
public class Stuff {
#Id
#Column(name = "stuff_id")
private Integer stuff_id;
// ...
#OneToOne(fetch = FetchType.LAZY)
#MapsId
#JoinColumn(name = "stuff_id")
private Task task_ref;
// ...
}
Only the parent needs to cascade to the Child entity, not the other way around.
The Parent only has an "inverse" side of the association.
The shared primary key is both a primary key and a foreign key in the Child entity
The MapsId annotation allows you to share the primary key for both the #Id and the OneToOne association
You could use the Task object as your id, see EmbeddedId or IdClass for an example. In case Stuff represents a subclass of the Task entity in your domain model, you should model this entity as such, in which you will have to represent the Stuff entity as a Joined Subclass of the Task entity. In both cases the extra Id in the Stuff entity is not needed anymore.

ManyToMany reflexive relationship with an extra coloumn in JPA

First of all, sorry for my english. This is my first post.
Im developing an app for a friend that uses JPA (EclipseLink) and i can´t figure out how to make a ManyToMany reflexive relationship with an extra column describing the relationship.
I tried the solution of this post (without using a bidirectional relation):
#Entity
#Table(name="relationships")
public class Relationship implements Serializable {
private static final long serialVersionUID = 1L;
#ManyToOne()
#JoinColumn(name = "associated_id_one")
private Person associatedPersonOne;
#ManyToOne()
#JoinColumn(name = "associated_id_two")
private Person associatedPersonTwo;
#Column(name="description")
private String description;
//Getters, Setters and constructor
...
}
But JPA gives me this error: The entity has no primary key attribute defined.
I know i have to specify a primary key but i don´t now how to make a composite primary key with those two foreign key.

Create Foreign key ON UPDATE CASCADE in JPA (eclipselink)

I am using CascadeType.MERGE but the generated sql does not contain any ON UPDATE in the foreign key. Here is my code
#Entity
public class Address {
#Id
private int id;
private String address;
}
#Entity
public class Employee {
#Id
private int empId;
#OneToOne(cascade = CascadeType.MERGE)
private Address address;
}
Is there anything missing here
CascadeType.MERGE is a JPA construct that tells the provider what when you call merge on Employee to also call merge on the referenced Address.
ON UPDATE CASCADE is a database setting that doesn't seem to have anything to do with CascadeType.merge. It causes the database to update foreign keys if the referenced primary key changes. Since changing primary keys in JPA is not allowed, this setting doesn't make sense. It is recommended you use sequencing for unique identifiers if you have a natural pk that might need to change.

Categories