#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")
Related
I have a User class and a Movie class which I want to merge into separate Lists. Once for movies that have been watched and one for the watchlist. Separately everything is fine but it seems that when I want to put them on both merges I get a duplication error even though they are saved in differently named columns.
#ManyToMany(cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
#JoinTable(name = "user_watch_list", joinColumns = #JoinColumn(name = "watche_User_ID", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "watch_Movie_id",referencedColumnName = "movieID"))
private List<Movie> watchList = new ArrayList<>();
#ManyToMany(cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
#JoinTable(name = "user_watched_movies", joinColumns = #JoinColumn(name = "watcheed_User_ID",referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "watched_movie_id",referencedColumnName = "movieID"))
private List<Movie> watchedMovies = new ArrayList<>();
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?
I have three tables. tbl_vendor and tbl_category tables are mapped using #ManyToMany relation. When I am getting 'Vendors' under a particular 'Category' I am also getting 'Areas' because tbl_vendor and tbl_area are also mapped using #ManyToMany.
relations:
in tbl_vendor Model :
#ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
#JoinTable(name = "tbl_category_vendor", joinColumns = {#JoinColumn(name = "vendor_id")}, inverseJoinColumns = {#JoinColumn(name = "category_id")})
private Set<Category> categories = new HashSet<>();
....
#ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
#JoinTable(name = "tbl_area_vendor", joinColumns = {#JoinColumn(name = "vendor_id")}, inverseJoinColumns = {#JoinColumn(name = "area_id")})
private Set<Area> areas = new HashSet<>();
in tbl_category Model :
#JsonIgnore
#ManyToMany(cascade = CascadeType.DETACH, mappedBy = "categories", fetch = FetchType.LAZY)
private List<Vendor> vendors = new ArrayList<>();
in tbl_area Model :
#JsonIgnore
#ManyToMany(mappedBy = "areas", fetch = FetchType.LAZY)
private List<Vendor> vendors = new ArrayList<>();
I have a particular case where I don't need this 'Area' with 'Vendor'.
is there any way to ignore already mapped 'Area' from 'Vendor' using JpaRepository in some particular case ?
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;
}
Given the following entity (some columns omitted from this long definition for brevity):
#Table(name = "Products")
public class Products implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "SKU")
private String sku;
#Basic(optional = false)
#Column(name = "ProductName")
private String productName;
private boolean allowPreOrder;
#ManyToMany(mappedBy = "productsCollection")
private Collection<Categories> categoriesCollection;
#JoinTable(name = "Products_CrossSell", joinColumns = {
#JoinColumn(name = "SKU", referencedColumnName = "SKU")}, inverseJoinColumns = {
#JoinColumn(name = "CrossSKU", referencedColumnName = "SKU")})
#ManyToMany
private Collection<Products> productsCollection;
#ManyToMany(mappedBy = "productsCollection")
private Collection<Products> productsCollection1;
#JoinTable(name = "Products_Related", joinColumns = {
#JoinColumn(name = "SKU", referencedColumnName = "SKU")}, inverseJoinColumns = {
#JoinColumn(name = "RelatedSKU", referencedColumnName = "SKU")})
#ManyToMany
private Collection<Products> productsCollection2;
#ManyToMany(mappedBy = "productsCollection2")
private Collection<Products> productsCollection3;
How do I get the set of related products for a given product SKU?
The products_related table looks like this:
I know how to get the answer using SQL but I'm new to JPA so I haven't quite grokked the API and query syntax yet.
It seems to me there are some unnecessary collections defined. Anyway:
#JoinTable(name = "Products_Related", joinColumns = {
#JoinColumn(name = "SKU", referencedColumnName = "SKU")}, inverseJoinColumns = {
#JoinColumn(name = "RelatedSKU", referencedColumnName = "SKU")})
#ManyToMany
private Collection<Products> productsCollection2;
This piece (it is present in your code) should give you the desired products. Just rename it to relatedProducts, and the respective setter/getter.
Update: You can get the object by:
Product p = entityManager.find(Product.class, yourProductId);
p.getRelatedProducts();
Obtaining the entity manager depends on your setup, and a better place to look for how to obtain it, is a tutorial.