Eclipselink + JPA generates ID column unexpectedly - jpa

Eclipselink generated a create table statement like so:
Create Table myTable (ID (255) not null, col1 (255), col2(255), col3(255) PK (ID, col1, col2)
#Embeddable
MyPK implements Serializable
{
#OneToOne
#Id
String col1;
#OneToOne
#Id
String col2;
...
}
#Entity
MyClass implements Serializable
{
#EmbeddedId
MyPK pk;
String col1;
String col2;
String col3;
...
}
How do I prevent the generation of the ID column in the Create Table statement? I ask because em.persist(MyClass) throws a constraint exception on ID being null. I expected that the #EmbeddedId would override this and prevent that field from being created.
EDIT
The table that I am trying to generate in code looks like so:
fk - col1
fk - col2
VarChar - col3

First issue is a String attribute can not be a OneToOne mappings. Second a OneToOne mapping can not be used within an EmbeddedId. Third you do not use the #Id annotation within an EmbeddedId as an Embeddable can not have identity.
The easiest way to do this is:
#Entity
#IdClass(MyPK.class)
MyClass implements Serializable
{
#OneToOne
#Id
TargetClass rel1;
#OneToOne
#Id
SecondTargetClass rel2
#Basic
String col3;
...
}
MyPK implements Serializable
{
String rel1;
String rel2;
...
}
If you really need an Embeddable for the pk class then replace the #ID annotation with #MapsId and add the EmbeddedId annotation back in MyClass and the Embeddable annotation back to MyPK

Related

JPA entity with composite primary that is also foreign key to same table

I have two tables A and B. There are two columns in table A, col1 and col2(both the columns are primary key, i.e. composite with col1 and col2). There is one column in table B, to which both the columns from table A are pointing to, i.e. col1 and col2 are foreign keys with relation to column in table B.
How can I implement the JPA entity for table A?
Thank you
Well you can achieve that by following code:
#Embeddable
public class AID {
public int xID;
public int yId;
}
#Entity
public class A {
#EmbeddedId
public AID id;
#OneToMany(mappedBy="A")
public Collection<B> b;
}
#Entity
public class Meeting {
#ID
#GeneratedValue
public Long id;
#MapsId("aID")
#JoinColumns({
#JoinColumn(name="xID", referencedColumnName="xID"),
#JoinColumn(name="yId", referencedColumnName="yId")
})
#ManyToOne
public A a;
}

JPA wrong number of columns

Using Spring Framework JPA I have an Entity
#Entity
#IdClass(ComposityKey.class)
#Table(name="table1")
public class Table1 {
#Id
#Column(name="tableId)
private int tableId;
#Id
private int tableId2;
...
}
2nd Entity contains a reference to Table1
#Entity
#Table(name = "table2")
public class Table2 {
#ManyToOne
#JoinColumn(name="tableId")
private Table1 table1;
}
Now I'm getting the obvious AnnotationException
A Foreign key refering Table1 from Table2 has the wrong number of column. should be 2
Table2 doesn't have tableId2 as a value
So how can i JoinColumn on a Composite Key?

JPA auto-generated key not reflected in foreign key of child table

Parent Table:
#Table(name="parent_table_t")
public class ParentTable implements Serializable {
#Id
#Column(name="contact_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer contactId;
---------
---------
#OneToOne (cascade = CascadeType.ALL, mappedBy = "parentTable")
private ChildTable childTable;
}
Child Table:
#Table(name="child_table_t")
public class ChildTable implements Serializable {
#Id
#Column(name="child_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer childId;
#Column(name="contact_id")
private Integer contactId;
#JoinColumn(name="contact_id", referencedColumnName = "contact_id", insertable=false, updatable=false)
#OneToOne(cascade = CascadeType.ALL)
private ParentTable parentTable;
}
My requirement is when contact_id is generated in Parent_table_t, it should be copied into contact_id of child_table_t when saved.
When I am calling saveAndFlush / save on Parent Table Entity, it is:
Generating the auto-increment for Parent->contact_id.
But Child_table_t -> contact_id is always null.
Can someone please help in this.
I am using in-memorty hsqldb with spring-boot and JPA.
You marked the relationship #JoinColumn with insertable=false, updatable=false, likely because you have an integer mapping for the column as well. Unfortunately, these settings prevent JPA from setting it with values from the relationship, which instead is forced to set the column with the value in the contactId attribute.
Put the insertable=false, updatable=false on the #Column instead.

Eclipselink JPA onetomany relationship

I am trying to model a simple OneToMany relationship with EclipseLink JPA & MySQL. It fails with some error messages. Can anyone help me to understand what it is missing ?
#Entity
public class Job implements Serializable {
#Id
#GeneratedValue
private long jobId;
#OneToMany(targetEntity=Applicant.class,mappedBy="job",cascade=CascadeType.ALL)
private List<Applicant> applicant;
//Gettters and Setters
}
#Entity
public class Applicant {
#Id
#GeneratedValue
private long applicantId;
#ManyToOne
#JoinColumn(name="job_Id")
private Job job;
//Gettters and Setters
}
TestCode
Job job=new Job ();
List <Applicant> applicants=new ArrayList<Applicant>();
Applicant applicant=new Applicant();
applicants.add(applicant);
job.setApplicant(applicants);
em.persist(job);// EntityManager Reff
Error message:
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'job_Id' in 'field list'
You need to have a foreign key column in your Applicant table.
You've annotated relation to Job with #JoinColumn(name="job_Id"). #JoinColumn is not necessary, because JPA is all about convention over configuration, which means there are default values which are implied if you don't override them. Without this annotation, EclipseLink would search for column named job_jobId (<field name>_<id column name in target table>). Since you stated that join column is job_Id, you need to have that column in Applicant table.
These are the database tables that should go with your entity mappings (with #JoinColumn(name = "job_Id")):
TABLE JOB
JOBID (PRIMARY KEY)
TABLE APPLICANT
APPLICANTID (PRIMARY KEY)
JOB_ID (FOREIGN KEY TO JOB#JOBID)
#Entity
public class Job implements Serializable{
#Id
#GeneratedValue
#Column(name="job_id")
private long jobId;
#OneToMany(mappedBy="job",cascade=CascadeType.ALL)
private List<Applicant> applicants;
public Job(){
applicants = new ArrayList<Applicant>();
}
public List<Applicant> getApplicants(){
//force clients through addApplicant() method to encapsulate setting both sides of relationship
return Collections.unmodifiableList(applicants);
}
public void addApplicant(Applicant applicant){
//set both sides of relationship
applicant.setJob(this);
applicants.add(applicant);
}
}
#Entity
public class Applicant {
#Id
#GeneratedValue
private long applicantId;
#ManyToOne
#JoinColumn(name="job_Id")
private Job job;
}
Job job = new Job ();
Applicant applicant = new Applicant();
job.addApplicant(applicant);
em.persist(job);

JPA #ManyToOne with different datatypes

I have two old database tables, that i need to use with JPA.
TOUR VEHICLE
----------------------- ---------------------
Id NUMBER(10) VehicleNumber CHAR(3)
VehicleNumber NUMBER(3) LicensePlate CHAR(10)
In my JPA entities I want tu use a #ManyToOne relationship from TOUR to VEHICLE.
Vehicle Entity:
public class Vehicle {
#Id
#Column(length=3)
private String VehicleNumber;
...
Tour Entity:
public class Tour {
#Id
#Column(precision=3)
private BigDecimal Id;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="VehicleNumber", referencedColumn="VehicleNumber")
private Vehicle vehicle;
...
But this of course doesn't work since the one vehicle number is translatet to String and the other is translatet to a BigDecimal(precision=3).
So what can i do to join them? Non-numeric values should be ignored.
Thanks for any advice.
VehicleNumber in TOUR table is a number while in the other one is CHAR.
First you need to match the types (better not to try to hack the standards).
then for #Id put the column name not #Column(precision=3). so it should be:
public class Tour {
#Id
#Column(name = "Id")
private BigDecimal id;
...
}
and do the same for the other table.
Oh by the way, I suggest you to use Long for the Primary Key not BigDecimal unless you have to.
But for entities, you are ok to work with Long