hibernate annotations one to many with composite foreign key - java

I have quite big problem with hibernate annotation mapping. Heres my diagram:
As for mapping object, few are simple cause its 1...N for:
TASK_DEF -> REPORT_DATA
REPORT_DATA -> REPORT_DATA_COLUMN
REPORT_DATA -> REPORT_DATA_VALUE
right?
Now problem is when I'm trying to map Collection of REPORT_DATA_VALUE to REPORT_DATA_COLUMN. I've tried this way:
#OneToMany(fetch = FetchType.LAZY)
#ForeignKey(name = "FK_REPORT_DATA_VALUE_REPORT_DA", inverseName = "PK_REPORT_DATA_COLUMN")
#JoinTable(name = "REPORT_DATA_VALUE", joinColumns = {
#JoinColumn(name = "REPORT_DATA_ID"),
#JoinColumn(name = "COLUMN_NM")
}, inverseJoinColumns = {
#JoinColumn(name = "REPORT_DATA_ID"),
#JoinColumn(name = "COLUMN_NM")
})
List<ReportDataValue> reportDataValueList;
But hibernate selects wrong identifies, therefore couldnt execute query. Could someone help me with this?

There is a problem in your code. Try this instead:
#OneToMany(fetch = FetchType.LAZY)
#JoinTable(name = "REPORT_DATA_VALUE", joinColumns = {
#JoinColumn(name = "REPORT_DATA_ID"),
}, inverseJoinColumns = {
#JoinColumn(name = "COLUMN_NM")
})
List<ReportDataValue> reportDataValueList;
By the way, If I were you, I wouldn't create a table for One To Many. I'd do this:
public class A{
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="B_ID")
B b;
}
public class B{
#OneToMany(mappedBy="b",fetch=FetchType.EAGER)
Set<A> as;
}

Related

Many To Many order by time it got added to post

#Entity
public class Post{
private Long id;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "tag_posts", joinColumns = #JoinColumn(name = "post_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "post_id", referencedColumnName = "id"))
private Set<Tag> hashtags= new LinkedHashSet<>();
}
Hello I would like to sort hashtags by right order they got added in to post, is anything like this possible?
Or would I just change type to List? Wouldnt this affect performance?
Thanks.
I assume you want to retrieve Post along with the tags but you want tags in the order it got added to the Post.
You can use #OrderBy annotation to get the list of tags while retrieving.
#Entity
public class Post{
private Long id;
#OrderBy(value="orderField")
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "tag_posts", joinColumns = #JoinColumn(name = "post_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "post_id", referencedColumnName = "id"))
private Set<Tag> hashtags= new LinkedHashSet<>();
}
If you want to create a column in the join table which will keep the same order you can use #OrderByColumn("orderField")

Double self-reference within the same entity using an extra join table

I want to create a double self-reference entity using an extra join table. I tried thus the following :
#Entity
#Table(name = "entity_a", schema="schema_a")
public class EntityA{
#Id
#Column(name = "id", unique = true, nullable = false)
private UUID id = UUID.randomUUID();
//skipped source code...
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "origin_child",
joinColumns =
{ #JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)},
inverseJoinColumns =
{ #JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)})
private EntityA child;
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "origin_child",
joinColumns =
{ #JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)},
inverseJoinColumns =
{ #JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)})
private EntityA origin;
//skipped source code...
}
When running my code I get the following error : org.hibernate.boot.spi.InFlightMetadataCollector$DuplicateSecondaryTableException: Table with that name [origin_child] already associated with entity
I tried thus to remove the origin field from EntityA and it worked. Now I am trying to figure out a way to join my EntityA.id and EntityA.origin_id over the already existing origin_child.child_id and origin_child.origin_id. Any idea how may I achieve that. Any alternative or better solution is more than welcome.
UPDATE :
I have tried the #JoinColumn alternative as following :
#OneToOne(fetch = FetchType.LAZY, mappedBy = "child")
private EntityA origin;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "child_id", referencedColumnName = "id", nullable = true)
private EntityA child;
Now when trying to update both origin and child instances :
child.setOrigin(origin);
entityARepository.save(child);
origin.setChild(child);
entityARepository.save(origin);
I get java.lang.StackOverflowError due to infinite recursion.
Any work around please?

Hibernate #JoinTable not working properly

I'm having this weird problem going on with my application when it comes to #JoinTable use.
I have 3 entities: EntityA, EntityB and EntityC.
EntityA.class
#OneToMany(fetch = FetchType.LAZY, mappedBy = "entityA")
public Set<EntityB> getEntityBSet() {
return entityBSet;
}
EntityB.class
#ManyToOne
#JoinColumn(name = "ID_ENTITY_A", nullable = false)
public EntityA getEntityA() {
return entityA;
}
#ManyToOne
#JoinTable(name = "B_AND_C",
joinColumns = { #JoinColumn(name = "ID_ENTITY_B") },
inverseJoinColumns = {#JoinColumn(name = "ID_ENTITY_C") })
public EntityC getEntityC() {
return entityC;
}
EntityC.class
#OneToMany(cascade = CascadeType.ALL, mappedBy="entityC")
public Set<EntityB> getEntityBSet() {
return entityBSet;
}
Everything works fine until I try to access entityB through entityA.getEntityBSet().
Hibernate doesnt generate the proper SQL for the relationship entityB.entityC, creating a Cartesian product:
SELECT ...
FROM ENTITY_B, B_C, ENTITY_C
WHERE B_C.ID_ENTITY_C = ENTITY_C.ID_ENTITY_C (+)
AND ENTITY_B.ID_ENTITY_A = ?
There should be the join between ENTITY_B and B_C:
AND ENTITY_B.ID_ENTITY_B = B_C.ID_ENTITY_B
On the other hand, when loading entityB through session.get(), the generated SQL is correct for that relationship (entityB.entityC).
Any help appreciated.

Ordered hibernate relationships

I have two entities, Books and Wishlist. My wish list contains books. I want to get the collection of books that are in my wish list ordered in the same order they were added to the wish list.
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "WISHLISTS_BOOKS", joinColumns = { #JoinColumn(name = "BOOK_ID") }, inverseJoinColumns = { #JoinColumn(name = "WISHLIST_ID") })
private Set<Book> books;
This is where I get stuck. There's an #OrderBy annotation but from what I understand it refers to a field in the book to use to order by. In my case, since a book can belong to multiple wish lists, I can't do that. Instead, I tried to create a added_ts timestamp field in the WISHLISTS_BOOKS join table but I'm not sure how to refer to it.
Can anyone help me sort this out?
You can use #OrderColumn(name = "added_ts") to achieve ordering.
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "WISHLISTS_BOOKS", joinColumns = { #JoinColumn(name = "BOOK_ID") }, inverseJoinColumns = { #JoinColumn(name = "WISHLIST_ID") })
#OrderColumn(name = "added_ts")
private Set<Book> books;

JPA many to one/one to many query

I would like to create JPA query based on this tables
**category**
(pk)CategoryID int (10)
category VARCHAR (45)
**templatecat**
(pk/fk)templateId int(10)
(pk/fk)categoryId int (10)
**template**
(pk)templateId int (10)
template madiumtext
I also have a "tempaltecat" table that holds foreign keys for category and template table.I`d like to create query that finds all templates in template table based on category and vice versa.
Here is my table mapping
#Entity
#Table(name = "category")
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "categoryId", unique = true) }, inverseJoinColumns = { #JoinColumn(name = "templateId") })
private Set<Template> template;
#Entity
#Table(name = "template")
#ManyToOne(optional = true)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "templateId") }, inverseJoinColumns = { #JoinColumn(name = "categoryId") })
private Category category;
Thanks in advance
It looks like a #ManyToMany relationship,
Instead of using #OneToMany and #ManyToMany, you can use the following configuration:
In Category class:
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "templatecat", joinColumns = { #JoinColumn(name = "categoryId", unique = true) }, inverseJoinColumns = { #JoinColumn(name = "templateId") })
private Set<Template> templates;
In Template class:
#Entity
#Table(name = "template")
#ManyMany(optional = true, mappedBy="templates");
private Set<Category> categories;
If you want to see all Templates of a given Category, the query would be:
select o.templates from Category o where o.id = ?
The reverse works as well (all Categories from a Template)
select o.categories from Template o where o.id = ?
Hope it has helped you.

Categories

Resources