About the use of JPA ElementCollection - java

I used the ElementCollection annotation on a List object,
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(
name = "a",
joinColumns = {#JoinColumn(name = "a_id", referencedColumnName = "a_id")},
foreignKey = #ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT)
)
private List<b> bs;
public class b{
#Column
private String bId;
#Column
private String bName;}
Is there a way to create a query dynamically through the name attribute in b by creating a Predicate

Related

Spring Boot Hibernate inserts Data into wrong Columns in Postgres

Initial Situation:
I have these two entities, GroceriesList and Product.
GroceriesList:
A GroceriesList can have several products.
#Entity
#Table(name = "lists")
public class GroceriesList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "list_id")
private Long listId;
#Column(name = "list_name")
private String listName;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "lists_products",
joinColumns = #JoinColumn(name = "product_id", referencedColumnName = "list_id"),
inverseJoinColumns = #JoinColumn(name = "list_id", referencedColumnName = "product_id")
)
private Set<Product> products;
}
Products:
A Product can be allocated to several GroceriesLists
#Entity
#Table(name = "products")
public class Product {
public enum Category {
Dairy,
Fruit,
Vegetable,
Meat,
Grains
}
// Product ID Column, GenerationType.Identity refers to auto incr in Postgres
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "product_id")
private Long productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_vendor")
private String productVendor;
#Enumerated(EnumType.STRING)
#Column(name = "product_category")
private Category productCategory;
#Column(name = "product_storedquantity")
private Integer productStoredQuantity;
#JsonIgnore
#ManyToMany(mappedBy = "products")
private List<GroceriesList> groceriesLists;
}
The entities and relationships are stored in three different tables in Postgres(One for Lists, one for products, and one mapping table for the relationships).
The mapping table:
Mapping Table "lists_products"
A sample Product:
Sample Product with Id=4
The problem: I'm trying to create new lists, and that works. However, as you can spot from the Mapping Table Image, Hibernate inserts the IDs into the wrong columns. The list_id in the mapping table is currently getting the product_id, and the product_id in the mapping table is getting the list_id.
I have tried to change the order of column names & references in the #JoinTable annotation in the GroceriesList Entity. However, that throws a mapping Error. I assume my error lies somewhere in that annotation. Interestingly, Hibernate uses the correct SQL-Query. What am I missing here?
After consulting fladdimir's solution, it gave me an idea and I solved my issue. The problem lied within the #JoinColumn annotation, where I thought the "name = ..." property refers to the column name in the database.
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "lists_products",
joinColumns = #JoinColumn(name = "product_id", referencedColumnName = "list_id"),
inverseJoinColumns = #JoinColumn(name = "list_id", referencedColumnName = "product_id")
)
private Set<Product> products;
However, that property refers to the declared variable inside the Entity in Spring Boot, i.e. listId
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "list_id")
private Long listId;
So, the working implementation of the #JoinTable Annotation should look like the following, where "name = ..." uses that variable name:
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "lists_products",
joinColumns = #JoinColumn(name = "listId", referencedColumnName = "list_id"),
inverseJoinColumns = #JoinColumn(name = "productId", referencedColumnName = "product_id")
)
private Set<Product> products;

Java Spring + Hibernate "Cannot add or update a child row"

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (ravermeister.artist_recordlabel, CONSTRAINT FK_9dgdyft45droyopxsqijwb1dx FOREIGN KEY (artist_id) REFERENCES artist (id))
Artist class
#Entity
#Repository
#Data
#NoArgsConstructor(force = true)
public class Artist {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "artist_firstname")
private String artist_firstname;
#Column(name = "artist_secondname")
private String artist_secondname;
#Column(name = "artist_nickname")
private String artist_nickname;
#ManyToMany (fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "artist_recordlabel", joinColumns = #JoinColumn(name = "artist_id"),
inverseJoinColumns = #JoinColumn(name = "label_id"))
private Set<RecordLabel> recordLabels;
#ManyToMany (fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable (name = "artist_musicrelease", joinColumns = #JoinColumn (name = "artist_id"),
inverseJoinColumns = #JoinColumn (name = "musicrelease_id"))
private Set <MusicRelease> musicReleaseSet;
and RecordLabel class
#Entity
#Repository
#Data
#NoArgsConstructor(force = true)
public class RecordLabel {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "label_name")
private String label_name;
#Column(name = "label_country")
private String label_country;
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "artist_recordlabel", joinColumns = #JoinColumn(name = "label_id"),
inverseJoinColumns = #JoinColumn(name = "artist_id"))
private Set<Artist> artistsList;
Please follow this guide for a many-to-many relation
http://www.baeldung.com/hibernate-many-to-many
I think this error means that you are trying to insert/update into RecordLabel table a artist_id value that does not exist in Artist table.

Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements

I have one lawyer table which is having id(int) as a primary key and Country table having country_code(String ) as a primary key. I want to create third table using #JoinTable annotation in hibernate with two foreign key in it. But when I run it following error is coming. Not sure how to map one string and one int as foreign keys in third table.
Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: com.test.common.entities.Country.lawyer
This is my code
#Entity
#Table(name = "lawyer")
public class Lawyer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "lawyer_batch_no")
private int lawyerbatchNo;
#ManyToOne(targetEntity = Country.class, cascade = { CascadeType.ALL })
#JoinTable(name = "lawyer_cscd", joinColumns = {
#JoinColumn(name = "lawyer_batch_no", referencedColumnName = "lawyer_batch_no") }, inverseJoinColumns = {
#JoinColumn(name = "country_code", referencedColumnName = "country_code") })
private Country country;
getter setter...
}
#Entity
#Table(name = "country")
public class Country {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "country_code")
protected String country_code;
#Column(name = "abbreviation")
protected String abbreviation;
#Column(name = "name", nullable = false)
protected String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "country")
protected Set<State> state = new HashSet<State>();
#OneToMany(targetEntity = Lawyer.class, cascade = { CascadeType.ALL }, orphanRemoval = true)
#JoinTable(name = "lawyer_cscd", joinColumns = {
#JoinColumn(name = "country_code", referencedColumnName = "country_code") }, inverseJoinColumns = {
#JoinColumn(name = "lawyer_batch_no", referencedColumnName = "lawyer_batch_no") })
private Lawyer lawyer;
getter setter....
}
The error indicates that private Lawyer lawyer needs to be a collection as it's a #OneToMany relationship. In the Country class, the last relationship should be
#OneToMany(targetEntity = Lawyer.class, cascade = { CascadeType.ALL }, orphanRemoval = true)
#JoinTable(name = "lawyer_cscd", joinColumns = {
#JoinColumn(name = "country_code", referencedColumnName = "country_code") }, inverseJoinColumns = {
#JoinColumn(name = "lawyer_batch_no", referencedColumnName = "lawyer_batch_no") })
private Set<Lawyer> lawyer;
// or a Collection/List/etc.

Order by using intermediate table column in JPA

I have Class Product (corresponding to PRODUCT table)
Class Product {
#Id
#Column(name = "PRODUCT_ID")
private Long id;
#Column(name = "NAME")
private String name;
//other attributes
}
I have another class Owner (corresponding to OWNER table)
Class Owner{
#Id
#Column(name = "OWNER_ID")
private Long id;
#Column(name = "NAME")
private String name;
}
I have an intermediate table named PRODUCT_OWNER (a product can have multiple owners).
The PRODUCT_OWNER table is something like this.
_______________________________________
| PRODUCT_ID | OWNER_ID | DISPLAY_ORDER |
|____________|__________|_______________|
Inside my Product class I have written a join statement to perform join using intermediate PRODUCT_OWNER table
#OneToMany(targetEntity = Owner.class, cascade = { CascadeType.ALL, CascadeType.MERGE }, fetch = FetchType.LAZY)
#JoinTable(name = "PRODUCT_OWNER",
joinColumns = { #JoinColumn(name = "PRODUCT_ID") },
inverseJoinColumns = { #JoinColumn(name = "OWNER_ID") })
private Set<Owner> productOwners = new HashSet<Owner>(0);
I have a column in my intermediate table as DISPLAY_ORDER. I want to sort the final Set productOwners using DISPLAY_ORDER. Is this possible in above approach. Please advice.
Hi you can try to add this to your JoinTable
#OneToMany(targetEntity = Owner.class, cascade = { CascadeType.ALL, CascadeType.MERGE }, fetch = FetchType.LAZY)
#JoinTable(name = "PRODUCT_OWNER",
joinColumns = { #JoinColumn(name = "PRODUCT_ID") },
inverseJoinColumns = { #JoinColumn(name = "OWNER_ID") })
#OrderColumn(name="DISPLAY_ORDER")
private List<Owner> productOwners = new HashSet<Owner>(0);

Hibernate criteria cannot retrieve values of a join

I have following entities and need to retrieve a list of names of all stores that are in a specific group and have branches in a specific city. Majority of tutorials and articles that Ive found are related to creating this type of relationships but none of them is about retrieval!
I changed the criteria for many times but Hibernate shows different errors for each. The commented parts of the code are those that I tried and the respective thrown exception is also written in front of each.
Entities
#Entity
public class Store {
#Id
String id;
String name;
#JoinTable(name = "store_groups", joinColumns = { #JoinColumn(name = "id", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "code", nullable = false, updatable = false) })
private Set<Group> groups = new HashSet<Group>(0);
private Set<StoreAddress> storeAddresses = new HashSet<StoreAddress>(0);
....
}
#Entity
public class Group {
#Id
String code;
#Column(nullable = false, unique = true)
String name;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "groups")
Set<Store> storees = new HashSet<Store>(0);
}
#Entity
#Table(name = "StoreAddresses")
#AssociationOverrides({
#AssociationOverride(name = "muJoinTable.store", joinColumns = #JoinColumn(name = "id", nullable = false)),
#AssociationOverride(name = "myJoinTable.city", joinColumns = #JoinColumn(name = "cityCode", nullable = false)) })
public class StoreAddress {
#EmbeddedId
private StoreCitysId myJoinTable = new StoreCitysId();
...
}
#Embeddable
public class StoreCitysId {
#ManyToOne
private Store store;
#ManyToOne
private City city;
}
#Entity
public class City {
#Id
short code;
#Column(nullable = false)
String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "myJoinTable.city")
private Set<StoreAddress> storeAddresses = new HashSet<StoreAddress>(
0);
}
Criteria
List<String> storees = (List<String>) sessionFactory
.getCurrentSession()
.createCriteria(Store.class)
.setProjection(
Projections.property("name").as(
"storeName"))
.createAlias("groups", "group")
.createAlias("storeAddresses", "address")
// .createAlias("address.myJoinTable.city", "city")
// .createAlias("address.myJoinTable", "myJoinTable")
// .createAlias("myJoinTable.city", "city") Error: Criteria objects cannot be created directly on components
.setFetchMode("group", FetchMode.JOIN)
.add(Restrictions.ilike("group.code", store))
.add(Restrictions.eq("address.myJoinTable.cityCode",
1)).list(); //city.code -> Error: could not resolve property: cityCode of:com.example.entity.StoreAddress address.myJoinTable.cityCode could not resolve property: myJoinTable.cityCode of:com.example.entity.StoreAddress
Your criterion Restrictions.eq("address.myJoinTable.cityCode", 1) doesn't reference a property but the name of the column. You could instead use address.myJoinTable.city and set the value to session.load(City.class, 1) making Restrictions.eq("address.myJoinTable.city", session.load(City.class, 1))
And this:
.createAlias("address.myJoinTable", "myJoinTable")
.createAlias("myJoinTable.city", "city")
Should be:
.createAlias("address.myJoinTable.city", "city")

Categories