How convert this SQL query into JPA criteriaBuilder query? - sql

I have the following Data Base diagram:
And I have the following quite simple SQL query:
SELECT Subject.id, Subject.name, subSelect.count
FROM
(SELECT Subject.id AS id, COUNT(*) AS count
FROM Question
JOIN Subject_Question ON Subject_Question.question_id = Question.id
JOIN Subject ON Subject.id = Subject_Question.subject_id
WHERE Subject.state = 0 AND Question.state = 0
GROUP BY Subject.id) AS subSelect
JOIN Subject ON Subject.id = subSelect.id
My task is to present this query Java application in term of criteriaBuilder from JPA.
This is my domain classes in Java application:
#Entity
#Table(name = "Question")
public class Question {
Long id;
String text;
ActiveUser activeUser;
Long dateCreation;
Long dateStateSetting;
EntityState state;
Set<Subject> subjects;
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "text", length = 5000, nullable = false)
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#ManyToOne(cascade = CascadeType.REMOVE)
#JoinColumn(name = "activeUser", nullable = false)
public ActiveUser getActiveUser() {
return activeUser;
}
public void setActiveUser(ActiveUser activeUser) {
this.activeUser = activeUser;
}
#Column(name = "dateCreation")
public Long getDateCreation() {
return dateCreation;
}
public void setDateCreation(Long dateCreation) {
this.dateCreation = dateCreation;
}
#Column(name = "dateStateSetting")
public Long getDateStateSetting() {
return dateStateSetting;
}
public void setDateStateSetting(Long dateStateSetting) {
this.dateStateSetting = dateStateSetting;
}
#Enumerated(EnumType.ORDINAL)
#Column(name = "state", nullable = false)
public EntityState getState() {
return state;
}
public void setState(EntityState state) {
this.state = state;
}
#ManyToMany(mappedBy = "questions")
public Set<Subject> getSubjects() {
return subjects;
}
public void setSubjects(Set<Subject> subjects) {
this.subjects = subjects;
}
}
And
#Entity
#Table(name = "Subject")
public class Subject {
Long id;
String name;
EntityState state;
Long dateCreation;
Boolean ifGroup;
List<Question> questions;
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Enumerated(EnumType.ORDINAL)
#Column(name = "state", nullable = false)
public EntityState getState() {
return state;
}
public void setState(EntityState state) {
this.state = state;
}
#Column(name = "dateCreation")
public Long getDateCreation() {
return dateCreation;
}
public void setDateCreation(Long dateCreation) {
this.dateCreation = dateCreation;
}
#Column(name = "ifGroup", nullable = false)
public Boolean getIfGroup() {
return ifGroup;
}
public void setIfGroup(Boolean ifGroup) {
this.ifGroup = ifGroup;
}
#ManyToMany(cascade = CascadeType.REMOVE)
#JoinTable(
name = "Subject_Question",
joinColumns = #JoinColumn(name = "subject_id"),
inverseJoinColumns = #JoinColumn(name = "question_id")
)
public List<Question> getQuestions() {
return questions;
}
public void setQuestions(List<Question> questions) {
this.questions = questions;
}
}
I start with the following:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Question> criteria = criteriaBuilder.createQuery(Question.class);
Root<Question> i = criteria.from(Question.class);
criteria.multiselect(
i.get("id"),
criteriaBuilder.count(i)).
But at this point I ran into a problem - I must to join with Subject_Question but I don't have class for it in Java application.
So is it possible to represent this SQL query in term of criteriaBuilder from JPA?

Related

Join Table with extra column

In my spring boot application I have user model, type model and user_type. Here a join table is created in the user model as user_type.
Model in maven project with jpa :
package com.example.pharmanic.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
#Entity
#Table( name = "users",
uniqueConstraints = {
#UniqueConstraint(columnNames = "username"),
#UniqueConstraint(columnNames = "email")
})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Size(max = 20)
private String username;
#NotBlank
#Size(max = 50)
#Email
private String email;
#NotBlank
#Size(max = 120)
private String password;
**#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id") ,
inverseJoinColumns = #JoinColumn(name = "role_id")
)**
private Set<Role> roles = new HashSet<>();
public User() {
}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
The join table user_role has two columns; user_id & role_id.
I want to add an extra column to user_role table to save more data relevant to user_role. A type String column should be added to the user_role table.

Cannot get Java #StoredProcedure to work, could not prepare statement

Hi,
I having problem with #StoredProcedureQuery just getting the error "could not prepare statement"? I am not sure why storedprocedure will not run , just keep getting this error:
"Caused by: org.h2.jdbc.JdbcSQLException: Function "SP_ARCHIVE_OLD_BOOKS" not found; SQL statement: call sp_archive_old_books(?,?) [90022-193]"
Named parameters are used for a callable statement, but database metadata indicates named parameters are not supported
#Entity
#Cacheable(value = true)
#Table(name = "Book")
#NamedStoredProcedureQuery(name = "archiveOldBooks", procedureName = "sp_archive_books",
parameters = {
#StoredProcedureParameter(name = "archiveDate", mode = ParameterMode.IN, type = Date.class),
#StoredProcedureParameter(name = "warehouse", mode = ParameterMode.IN, type = String.class),
#StoredProcedureParameter(name = "maxBookArchived", mode = ParameterMode.INOUT, type = Integer.class)
})
#NamedQuery(name = FIND_ALL_BOOKS, query = "select b from Book b")
#SequenceGenerator(name = "SEQ_BOOK", initialValue = 50)
public class Book {
public static final String FIND_ALL_BOOKS = "book.findAllBooks";
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_BOOK")
private int id;
#NotNull
#Min(1)
private Integer quantity;
#NotNull
#AllItemTypes
#Enumerated(EnumType.STRING)
private ItemType itemType;
#NotNull
#Title
private String title;
#NotNull
#Price
private Float price;
#NotNull
#Description
private String description;
#NotNull
#Isbn
private String isbnNumber;
#NotNull
#InitDate
private Date initDate;
#NotNull(message = "Invalid illustration is set to null")
private Boolean illustrations;
#NotNull
#PageNumber
private Integer numberOfPages;
#NotNull
#Version
#Min(1)
private Integer version;
#NotNull
#Author
private String author;
#NotNull
#Min(1519)
private Integer year;
// ======================================
// = Constructors =
// ======================================
public Book(){
}
public Book(Integer quantity, ItemType itemType, String title, Float price, String description, String isbnNumber, Date initDate, Boolean illustrations, Integer numberOfPages, Integer version, String author, Integer year) {
this.quantity = quantity;
this.itemType = itemType;
this.title = title;
this.price = price;
this.description = description;
this.isbnNumber = isbnNumber;
this.initDate = initDate;
this.illustrations = illustrations;
this.numberOfPages = numberOfPages;
this.version = version;
this.author = author;
this.year = year;
}
public static String getFindAllBooks() {
return FIND_ALL_BOOKS;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public ItemType getItemType() {
return itemType;
}
public void setItemType(ItemType itemType) {
this.itemType = itemType;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIsbnNumber() {
return isbnNumber;
}
public void setIsbnNumber(String isbnNumber) {
this.isbnNumber = isbnNumber;
}
public Date getInitDate() {
return initDate;
}
public void setInitDate(Date initDate) {
this.initDate = initDate;
}
public Boolean getIllustrations() {
return illustrations;
}
public void setIllustrations(Boolean illustrations) {
this.illustrations = illustrations;
}
public Integer getNumberOfPages() {
return numberOfPages;
}
public void setNumberOfPages(Integer numberOfPages) {
this.numberOfPages = numberOfPages;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
#Override
public String toString() {
return "Book{" +
"id=" + id +
", quantity=" + quantity +
", itemType=" + itemType +
", title='" + title + '\'' +
", price=" + price +
", description='" + description + '\'' +
", isbnNumber='" + isbnNumber + '\'' +
", initDate=" + initDate +
", illustrations=" + illustrations +
", numberOfPages=" + numberOfPages +
", version=" + version +
", author='" + author + '\'' +
", year=" + year +
'}';
}
}
public abstract class AbstractPeristEntityClass {
protected static EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
protected EntityManager em;
protected EntityTransaction tx;
#Before
public void initEntityManager() throws Exception {
em = emf.createEntityManager();
tx = em.getTransaction();
}
#After
public void closeEntityManager() throws SQLException {
if (em != null) em.close();
}
protected Long getRandomId() {
return Math.abs(new Random().nextLong());
}
}
public interface Constants {
String PERSISTENCE_UNIT_NAME = "TEST";
}
public class Book_v2_IT extends AbstractPeristEntityClass {
#Test
public void shouldCallANamedStoredProcedureQuery() throws Exception {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("archiveOldBooks");
// Set the parameters and execute
query.setParameter("archiveDate", new Date());
query.setParameter("maxBookArchived", 1000);
query.execute();
}
#Test
public void shouldCallAStoredProcedureQuery() throws Exception {
StoredProcedureQuery query = em.createStoredProcedureQuery("sp_archive_old_books");
query.registerStoredProcedureParameter("archiveDate", Date.class, ParameterMode.IN);
query.registerStoredProcedureParameter("maxBookArchived", Integer.class, ParameterMode.IN);
// Set the parameters and execute
query.setParameter("archiveDate", new Date());
query.setParameter("maxBookArchived", 1000);
query.execute();
}
}

Could not deserialize - POJO file error

Using Netbeans 'Create mapping & POJO files from Database' I am receiving this error:
INFO: HHH000327: Error performing load command : org.hibernate.type.SerializationException: could not deserialize
org.hibernate.type.SerializationException: could not deserialize
at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:262)
at org.hibernate.internal.util.SerializationHelper.deserialize(SerializationHelper.java:306)
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.fromBytes(SerializableTypeDescriptor.java:155)
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:130)
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:44)
at org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor$2.doExtract(VarbinaryTypeDescriptor.java:71)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:263)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:259)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:249)
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:334)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2969)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.loadFromResultSet(EntityReferenceInitializerImpl.java:324)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.hydrateEntityState(EntityReferenceInitializerImpl.java:251)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:107)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:255)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4120)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:145)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1066)
at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:972)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:173)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at yy.mavenproject2.Bpauser_$$_jvst210_0.getFullName(Bpauser_$$_jvst210_0.java)
at yy.mavenproject2.PP.main(PP.java:29)
Caused by: java.io.StreamCorruptedException: invalid stream header: 786F0607
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:328)
at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:318)
at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:237)
... 31 more
And here are PP.java:
package yy.mavenproject2;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import yy.mavenproject2.Bpauser;
public class PP {
public static void main(String[] args) {
Session session = null;
try {
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(ssrb.build());
session = sessionFactory.openSession();
if (session.isConnected()) {
String number = "1";
Bpauser emp = (Bpauser) session.load(Bpauser.class, number);
System.out.println("ID is " + emp.getId());
System.out.println("Full Name is " + emp.getFullName());
// System.out.println("E-Mail is " + emp.getEmail());
session.close();
} else {
System.out.println("Connection faiied");
}
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
and Bpauser.java:
package yy.mavenproject2;
// Generated Nov 25, 2015 1:43:19 PM by Hibernate Tools 4.3.1
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
/**
* Bpauser generated by hbm2java
*/
#Entity
#Table(name = "BPAUSER", schema = "BPA", uniqueConstraints = #UniqueConstraint(columnNames = {"USERNAME", "ACTIVE", "DEACTIVATION_DATE"})
)
public class Bpauser implements java.io.Serializable {
private String id;
private long version;
private Bpauser bpauser;
private String password;
private String region;
private String surName;
private String firstName;
private String department;
private String company;
private String country;
private String branch;
private String fullName;
private String username;
private String email;
private String location;
private String displayName;
private boolean active;
private Serializable modified;
private Boolean ignoreInSync;
private Boolean receiveNewTaskEmail;
private BigDecimal cbdSyncVersion;
private Serializable deactivationDate;
private Set bpausers = new HashSet(0);
public Bpauser() {
}
public Bpauser(String id, boolean active) {
this.id = id;
this.active = active;
}
public Bpauser(String id, Bpauser bpauser, String password, String region, String surName, String firstName, String department, String company, String country, String branch, String fullName, String username, String email, String location, String displayName, boolean active, Serializable modified, Boolean ignoreInSync, Boolean receiveNewTaskEmail, BigDecimal cbdSyncVersion, Serializable deactivationDate, Set bpausers) {
this.id = id;
this.bpauser = bpauser;
this.password = password;
this.region = region;
this.surName = surName;
this.firstName = firstName;
this.department = department;
this.company = company;
this.country = country;
this.branch = branch;
this.fullName = fullName;
this.username = username;
this.email = email;
this.location = location;
this.displayName = displayName;
this.active = active;
this.modified = modified;
this.ignoreInSync = ignoreInSync;
this.receiveNewTaskEmail = receiveNewTaskEmail;
this.cbdSyncVersion = cbdSyncVersion;
this.deactivationDate = deactivationDate;
this.bpausers = bpausers;
}
#Id
#Column(name = "ID", unique = true, nullable = false, length = 1020)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
#Version
#Column(name = "VERSION", nullable = false, precision = 10, scale = 0)
public long getVersion() {
return this.version;
}
public void setVersion(long version) {
this.version = version;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "SUPERIOR_USER_ID")
public Bpauser getBpauser() {
return this.bpauser;
}
public void setBpauser(Bpauser bpauser) {
this.bpauser = bpauser;
}
#Column(name = "PASSWORD", length = 400)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "REGION", length = 12)
public String getRegion() {
return this.region;
}
public void setRegion(String region) {
this.region = region;
}
#Column(name = "SUR_NAME", length = 200)
public String getSurName() {
return this.surName;
}
public void setSurName(String surName) {
this.surName = surName;
}
#Column(name = "FIRST_NAME", length = 200)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "DEPARTMENT", length = 60)
public String getDepartment() {
return this.department;
}
public void setDepartment(String department) {
this.department = department;
}
#Column(name = "COMPANY", length = 200)
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
#Column(name = "COUNTRY", length = 8)
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
#Column(name = "BRANCH", length = 16)
public String getBranch() {
return this.branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
#ManyToOne(fetch = FetchType.LAZY)
#Column(name = "FULL_NAME", length = 400)
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#Column(name = "USERNAME", length = 400)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "EMAIL", length = 300)
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "LOCATION", length = 20)
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
#Column(name = "DISPLAY_NAME", length = 400)
public String getDisplayName() {
return this.displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
#Column(name = "ACTIVE", nullable = false, precision = 1, scale = 0)
public boolean isActive() {
return this.active;
}
public void setActive(boolean active) {
this.active = active;
}
#Column(name = "MODIFIED")
public Serializable getModified() {
return this.modified;
}
public void setModified(Serializable modified) {
this.modified = modified;
}
#Column(name = "IGNORE_IN_SYNC", precision = 1, scale = 0)
public Boolean getIgnoreInSync() {
return this.ignoreInSync;
}
public void setIgnoreInSync(Boolean ignoreInSync) {
this.ignoreInSync = ignoreInSync;
}
#Column(name = "RECEIVE_NEW_TASK_EMAIL", precision = 1, scale = 0)
public Boolean getReceiveNewTaskEmail() {
return this.receiveNewTaskEmail;
}
public void setReceiveNewTaskEmail(Boolean receiveNewTaskEmail) {
this.receiveNewTaskEmail = receiveNewTaskEmail;
}
#Column(name = "CBD_SYNC_VERSION", scale = 0)
public BigDecimal getCbdSyncVersion() {
return this.cbdSyncVersion;
}
public void setCbdSyncVersion(BigDecimal cbdSyncVersion) {
this.cbdSyncVersion = cbdSyncVersion;
}
#Column(name = "DEACTIVATION_DATE")
public Serializable getDeactivationDate() {
return this.deactivationDate;
}
public void setDeactivationDate(Serializable deactivationDate) {
this.deactivationDate = deactivationDate;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "bpauser")
public Set getBpausers() {
return this.bpausers;
}
public void setBpausers(Set bpausers) {
this.bpausers = bpausers;
}
}
Could you please assist? I can't find why I have the error related to getter getFullName(). Any comments will be very useful.
OK I found the problem myself. DB has type timestamp(6), I had serialized type of variables with those timestamps. So I changed in POJO this serialized type to Date. Solved.

Select a child from a Parent through CriteriaQuery through subqueries

Does any have anyone have an idea of how i can return an distinct array of product from a ProductCategory through CriteriaQuery using subqueries! I tried these tutorial but it didn't work:
Subquery in where clause with CriteriaQuery
public String[] getProductsDistinctByName(String category) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Object[]> criteriaQuery = builder.createQuery(Object[].class);
Subquery<Productscategory> subquery =criteriaQuery.subquery(Productscategory.class);
Root productsCategory = criteriaQuery.from(Productscategory.class);
subquery.select(productsCategory.<Integer>get(Productscategory_.productscategoryid))
.where(builder.equal((productsCategory.<String>get(Productscategory_.productscategoryid)), category));
Root<Products> root = criteriaQuery.from(Products.class);
criteriaQuery.multiselect(root.get(Products_.productname)).distinct(true)
.where(builder.in(root.get("productscategoryid")).value(subquery));
List<Object[]> tupleResult = em.createQuery(criteriaQuery).getResultList();
String[] arrayProducts = new String[tupleResult.size()];
for (int i = 0; i < tupleResult.size(); i++) {
arrayProducts[i] = (String) tupleResult.get(0).toString();
}
return arrayProducts;
}
and
public String[] getProductsDistinctBySubQueriesName(String category) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
//subquery
Subquery<Integer> subqueries = criteria.subquery(Integer.class);
Root<Productscategory> productCategory = subqueries.from(Productscategory.class);
subqueries.select(productCategory.<Integer>get(Productscategory_.productscategoryid))
.where(builder.equal((productCategory.<String>get("productcatgoryname")), category));
//outerquery
Root<Products> root = criteria.from(Products.class);
criteria.multiselect(root.get(Products_.productname)).distinct(true)
.where(builder.in(root.get("productscategoryid")).value(subqueries));
List<Tuple> tupleResult = em.createQuery(criteria).getResultList();
String[] arrayProducts = new String[tupleResult.size()];
for (int i = 0; i < tupleResult.size(); i++) {
arrayProducts[i] = (String) tupleResult.get(i).get(0);
}
return arrayProducts;
}
Here is the entity
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "productscategory")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Productscategory.findAll", query = "SELECT p FROM Productscategory p"),
#NamedQuery(name = "Productscategory.findByProductscategoryid", query = "SELECT p FROM Productscategory p WHERE p.productscategoryid = :productscategoryid"),
#NamedQuery(name = "Productscategory.findByProductcatgoryname", query = "SELECT p FROM Productscategory p WHERE p.productcatgoryname = :productcatgoryname"),
#NamedQuery(name = "Productscategory.findByProductcategorycomments", query = "SELECT p FROM Productscategory p WHERE p.productcategorycomments = :productcategorycomments"),
#NamedQuery(name = "Productscategory.findByStatusid", query = "SELECT p FROM Productscategory p WHERE p.statusid = :statusid")})
public class Productscategory implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "productscategoryid")
private Integer productscategoryid;
#Basic(optional = false)
#Column(name = "productcatgoryname")
private String productcatgoryname;
#Basic(optional = false)
#Column(name = "productcategorycomments")
private String productcategorycomments;
#Basic(optional = false)
#Column(name = "statusid")
private String statusid;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "productcategoryid")
private Collection<Priceitem> priceitemCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "productcategoryid")
private Collection<Productssupplied> productssuppliedCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "productscategoryid")
private Collection<Products> productsCollection;
public Productscategory() {
}
public Productscategory(Integer productscategoryid) {
this.productscategoryid = productscategoryid;
}
public Productscategory(Integer productscategoryid, String productcatgoryname, String productcategorycomments, String statusid) {
this.productscategoryid = productscategoryid;
this.productcatgoryname = productcatgoryname;
this.productcategorycomments = productcategorycomments;
this.statusid = statusid;
}
public Integer getProductscategoryid() {
return productscategoryid;
}
public void setProductscategoryid(Integer productscategoryid) {
this.productscategoryid = productscategoryid;
}
public String getProductcatgoryname() {
return productcatgoryname;
}
public void setProductcatgoryname(String productcatgoryname) {
this.productcatgoryname = productcatgoryname;
}
public String getProductcategorycomments() {
return productcategorycomments;
}
public void setProductcategorycomments(String productcategorycomments) {
this.productcategorycomments = productcategorycomments;
}
public String getStatusid() {
return statusid;
}
public void setStatusid(String statusid) {
this.statusid = statusid;
}
#XmlTransient
public Collection<Priceitem> getPriceitemCollection() {
return priceitemCollection;
}
public void setPriceitemCollection(Collection<Priceitem> priceitemCollection) {
this.priceitemCollection = priceitemCollection;
}
#XmlTransient
public Collection<Productssupplied> getProductssuppliedCollection() {
return productssuppliedCollection;
}
public void setProductssuppliedCollection(Collection<Productssupplied> productssuppliedCollection) {
this.productssuppliedCollection = productssuppliedCollection;
}
#XmlTransient
public Collection<Products> getProductsCollection() {
return productsCollection;
}
public void setProductsCollection(Collection<Products> productsCollection) {
this.productsCollection = productsCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (productscategoryid != null ? productscategoryid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Productscategory)) {
return false;
}
Productscategory other = (Productscategory) object;
if ((this.productscategoryid == null && other.productscategoryid != null) || (this.productscategoryid != null && !this.productscategoryid.equals(other.productscategoryid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.inventory.entity.Productscategory[ productscategoryid=" + productscategoryid + " ]";
}
}
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "products")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Products.findAll", query = "SELECT p FROM Products p"),
#NamedQuery(name = "Products.findByProductid", query = "SELECT p FROM Products p WHERE p.productid = :productid"),
#NamedQuery(name = "Products.findByProductname", query = "SELECT p FROM Products p WHERE p.productname = :productname"),
#NamedQuery(name = "Products.findByMarketname", query = "SELECT p FROM Products p WHERE p.marketname = :marketname"),
#NamedQuery(name = "Products.findByModelvariant", query = "SELECT p FROM Products p WHERE p.modelvariant = :modelvariant"),
#NamedQuery(name = "Products.findByManufacturer", query = "SELECT p FROM Products p WHERE p.manufacturer = :manufacturer"),
#NamedQuery(name = "Products.findByProductdescription", query = "SELECT p FROM Products p WHERE p.productdescription = :productdescription"),
#NamedQuery(name = "Products.findByStatusid", query = "SELECT p FROM Products p WHERE p.statusid = :statusid")})
public class Products implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "productid")
private Integer productid;
#Basic(optional = false)
#Column(name = "productname")
private String productname;
#Basic(optional = false)
#Column(name = "marketname")
private String marketname;
#Basic(optional = false)
#Column(name = "modelvariant")
private String modelvariant;
#Basic(optional = false)
#Column(name = "manufacturer")
private String manufacturer;
#Column(name = "productdescription")
private String productdescription;
#Basic(optional = false)
#Column(name = "statusid")
private String statusid;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "productid")
private Collection<Productssupplied> productssuppliedCollection;
#JoinColumn(name = "productscategoryid", referencedColumnName = "productscategoryid")
#ManyToOne(optional = false)
private Productscategory productscategoryid;
public Products() {
}
public Products(Integer productid) {
this.productid = productid;
}
public Products(Integer productid, String productname, String marketname, String modelvariant, String manufacturer, String statusid) {
this.productid = productid;
this.productname = productname;
this.marketname = marketname;
this.modelvariant = modelvariant;
this.manufacturer = manufacturer;
this.statusid = statusid;
}
public Integer getProductid() {
return productid;
}
public void setProductid(Integer productid) {
this.productid = productid;
}
public String getProductname() {
return productname;
}
public void setProductname(String productname) {
this.productname = productname;
}
public String getMarketname() {
return marketname;
}
public void setMarketname(String marketname) {
this.marketname = marketname;
}
public String getModelvariant() {
return modelvariant;
}
public void setModelvariant(String modelvariant) {
this.modelvariant = modelvariant;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getProductdescription() {
return productdescription;
}
public void setProductdescription(String productdescription) {
this.productdescription = productdescription;
}
public String getStatusid() {
return statusid;
}
public void setStatusid(String statusid) {
this.statusid = statusid;
}
#XmlTransient
public Collection<Productssupplied> getProductssuppliedCollection() {
return productssuppliedCollection;
}
public void setProductssuppliedCollection(Collection<Productssupplied> productssuppliedCollection) {
this.productssuppliedCollection = productssuppliedCollection;
}
public Productscategory getProductscategoryid() {
return productscategoryid;
}
public void setProductscategoryid(Productscategory productscategoryid) {
this.productscategoryid = productscategoryid;
}
#Override
public int hashCode() {
int hash = 0;
hash += (productid != null ? productid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Products)) {
return false;
}
Products other = (Products) object;
if ((this.productid == null && other.productid != null) || (this.productid != null && !this.productid.equals(other.productid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.inventory.entity.Products[ productid=" + productid + " ]";
}
}

Hibernate : #OneToMany : Always deleting and reinserting the child records

Please help me resolve this issue. I tried googling for a solution and couldn't find one for this.
Table structure
Table: Catalog
catalog_id (primary key)
name
Table: Catalog_Locale
catalog_id
locale_id
sequence
composite key(catalog_id,locale_id)
Class
public Class Catalog{
#Id
#Column(name = "CATALOG_ID", nullable = false)
private String catalogId;
#Column(name = "NAME")
private String name;
#OneToMany(targetEntity = CatalogLocale.class,fetch=FetchType.LAZY)
#JoinColumn(name = "CHILD_CATALOG_ID", nullable = false)
#Cascade(value = {})
protected List<CatalogLocale> locales = new ArrayList<CatalogLocale>(10);
public void setCatalogId( String catalogId ){
this.catalogId = catalogId;
}
public void setName( String name ){
this.name = name;
}
public void setLocales( List<CatalogLocale> locales ){
this.locales = locales;
}
public void getCatalogId(){
return catalogId;
}
public void getName(){
return name;
}
public void getLocales(){
return locales;
}
}
public class CatalogLocale{
#EmbeddedId
CatalogLocalePk catalogLocalePk;
#Column(name = "SEQUENCE")
private int sequence;
public void setCatalogLocalePk( CatalogLocalePk catalogLocalePk ){
this.catalogLocalePk = catalogLocalePk;
}
public void setSequence( int sequence ){
this.sequence = sequence;
}
public CatalogLocalePk getCatalogLocalePk(){
return catalogLocalePk;
}
public int getSequence(){
return sequence;
}
#Embeddable
public static class CatalogLocalePk{
#Column(name = "CATALOG_ID", nullable = false)
private String catalogId;
#Column(name = "LOCALE_ID", nullable = false)
private String localeId;
public CatalogLocalePk(){
}
public CatalogLocalePk( String catalogId, String localeId ){
this.catalogId = catalogId;
this.localeId = localeId;
}
public void setCatalogId( String catalogId ){
this.catalogId = catalogId;
}
public void setLocaleId( String localeId ){
this.localeId = localeId;
}
public String getCatalogId(){
return catalogId;
}
public String getLocaleId(){
return localeId;
}
}
}
The code works for fine for the insert operation, but for any update to the Catalog will trigger for delete and reinsert all entries of the child table.
Is there any solution for this?