I am struggling to map my EF6 classes to table structure. Here is my table structure:
**TableA:**
Id (PK),
Name,
BId (FK to TableB), NULLABLE
**TableB:**
Id (PK),
Prop1,
Prop2
My classes are:
class TableA
{
int Id;
string Name;
int BId;
TableB bObject;
}
//TableB doesnt need to know about TableA
class TableB
{
int Id;
string prop1;
string prop2;
}
I want to use a configuration for TableA to something like:
HasRequired(a => a.bObject).WithOptional().HasForeignKey(a => a.BId);
However, this is not working. How do I fix this?
Thanks
Vik
Related
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;
}
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?
i have Entity mapped to table TABLE1 with columns COLUMN1 and COLUMN2
i have class ResViewer
public class ResViewer() {
private boolean flag;
private int property;
...selectors
}
i have entity class
#Entity
#Table(name="TABLE1")
public class Table1() {
#Id
private long id;
private ResViewer res1;
private ResViewer res2;
...selectors
}
How can i map field flag of classes res1 and res2 to columnds COLUMN1 and COLUMN2?
Your ResViewer needs to be annotated with #Embeddable, and the fields res1 and res2 must be annotated with #Embedded, and with #AttributeOverrides, as demonstrated in the javadoc of #Embedded.
Say I have this class:
#Entity
#Table(name="PICTURE")
public class Picture{
private String category1, category2;
}
but the database structure looks like this:
TABLE PICTURE {
int category1;
int category2;
...
}
TABLE PICTURE_REF {
int category;
String categoryName;
...
}
How would I use JPA annotations on Picture so that any time I request an instance of it, category1 and category2 contains the categoryName from the PICTURE_REF table instead of the actual integer id stored in the PICTURE table?
I'm also wondering how saves would work because the user would select a category from a dropdown and the corresponding category integer ID would be what's stored in the PICTURE table.
From your description , PICTURE.category1 and PICTURE.category2 have the many-to-one relationship to the PICTURE_REF
The following shows the bi-directional mapping between them using annotation:
For table PICTURE:
#Entity
#Table(name="PICTURE")
public Class Picture{
#Id
private Integer id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "category1")
private PictureRef category1,
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "category2")
private PictureRef category2;
//getter and setters
}
For table PICTURE_REF:
#Entity
#Table(name="PICTURE_REF")
public Class PictureRef{
#Id
private Integer id;
#OneToMany(mappedBy = "category1")
List <Picture> listOfCat1Picture= new ArrayList<Picture>();
#OneToMany(mappedBy = "category2")
List <Picture> listOfCat2Picture= new ArrayList<Picture>();
//getter and setters
}
Important Points:
#Entity marks the java class as an hibernate entity. It is mapped to the name of the table specified in the #Table
Use #ManyToOne to define the many-to-one relationship
In the relational database , many-to-one relationship is expressed by using the following foreign key constraint:
"Many side table" has a FK column which only accepts the PK of the "one side table".
In your case , these FK columns are PICTURE.category1 and PICTURE.category2. The name of these FK columns can be explicitly defined by the name attribute of #JoinColumn.
FetchType.EAGER makes that PictureRef will be eagerly fetched whenever Picture is loaded or get
Depending on your requirement , you can do the unidirectional mapping by omitting #OneToMany in the PictureRef.It will also work .But given PictureRef , you cannot access its Picture
Given a Picture instance , you can get its categoryName and categoryId by
picture.getCategory1().getCategoryName()
picture.getCategory1().getId()
picture.getCategory2().getCategoryName()
picture.getCategory2().getId()
If you can't modify the schema
You can modify your mapping so Category is an entity instead of just a String. Then you would have a OneToOne or (more likely) a ManyToOne from Picture to Category for category1 and category2.
If you CAN modify the schema
You can use an ElementCollection on Picture to store a List instead of having category1 and category2. This would give you a schema something like
TABLE PICTURE {
long key;
}
TABLE PICTURE_CATEGORY {
long picture_key;
String category_name;
}
OR you can again map Category to an entity and use a ManyToMany from Picture to Category which would give you a schema like
TABLE PICTURE {
long key;
...
}
TABLE PICTURE_CATEGORY {
long picture_key;
long category_key;
}
TABLE CATEGORY {
long key;
String name;
}
As for saving, you will can use a converter in whatever your view technology is that will converter from key to Category, or you can load the Category from the key in your controller and set it in the Picture before you save. I doubt you'll want saving a Picture to cascade into a Category.
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