How to use In clause in JPQL query with subquery - java

I have a entity classes as below
ExportMO.java
#Entity
#Table(name = "DATAEXPORTTEMPLATE")
#NamedQueries({
#NamedQuery(name = "ExportTemplateMO.getTemplatesByUser", query = "SELECT DISTINCT template FROM ExportTemplateMO template " +
"join template.fields exportFields WHERE template.eId IN (SELECT S1.dcid FROM SchoolMO S1 join S1.fields S2 WHERE S2.dcid = :userDCID)")
})
public class ExportMO implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "DATATEMPLATEID", unique = true, nullable = false)
private Long templateId;
#Column(name = "EID", nullable = true)
private Long eId;
#OneToMany(fetch=FetchType.EAGER, mappedBy="templateMO", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<ExportFieldMO> fields;
}
SchoolMO.java
#Entity
#Table(name = "SCHOOLSTAFF")
public class SchoolMO implements Serializable {
#Id
#Column(name = "DCID", unique = true, nullable = false)
private Long dcid;
#Column(name = "ID", unique = true)
private Long id;
#Column(name = "USERS_DCID", unique = false, nullable = false)
#JoinColumn(name="USERS_DCID",referencedColumnName="USERS_DCID",nullable=false)
private Long users_dcid;
#OneToMany(fetch=FetchType.EAGER, mappedBy="users_dcid", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<SchoolStaffLeanMO> fields;
}
Can someone help me how to use this using the IN clause for subquery.
If i try to use the same '=' instead of 'IN' i am able to get the results.
Thanks in advance.

Related

Getting error Parameter value [1465] did not match expected type [java.util.Set (n/a)] while fetchimg data from JPA

I am getting Data from MySql using Spring Data JPA. I getting this error when I am passing provider as 1465 in request.
I have tried Sending Set from the request as well.
My calling code is :
offerList = blackholeDetailRepository.findByProductVMS(ProductType.VMS, blackholeID,
pricingCopyRequestBO.getProviderId().longValue(),
OfferGradeConstant.fromString(pricingCopyRequestBO.getOfferGrade()));
Code in repository is :
#Query("SELECT detail FROM #{#entityName} AS detail JOIN FETCH detail.vmsRestrictedProviders AS provider "+
"WHERE detail.product = :product " + "AND detail.master.id= :masterId "
+ "AND detail.vmsRestrictedProviders = :providerId " + "AND provider.offerGrade= :offerGrade")
Set<BlackholeDetailEntity> findByProductVMS(#Param("product") ProductType product, #Param("masterId") Long masterId,
#Param("providerId") Long providerId, #Param("offerGrade") OfferGradeConstant offerGrade);
BlackholeDetailEntity Entity is :
#Entity
#Table(name = "blackhole_detail")
#Data
#EqualsAndHashCode(callSuper = true)
public class BlackholeDetailEntity extends PolygonDetailEntity {
private static final long serialVersionUID = 1L;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "blackhole_entity_mapping",
joinColumns = #JoinColumn(name = "detail_id", referencedColumnName = "id"))
#Column(name = "entity_id")
private Set<Integer> entities;
#Convert(converter = CsvStringSetConverter.class)
private Set<String> restrictedOffers;
#Convert(converter = CsvLongSetConverter.class)
#Column(name = "ll_me_restricted_providers", columnDefinition = "text")
private Set<Long> llMERestrictedProviders;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,
orphanRemoval = true, mappedBy = "blackHole")
private Set<VmsProviderRestrictionEntity> vmsRestrictedProviders;
#Column(name = "is_restrict_all")
private Boolean restrictAll;
}
VmsProviderRestrictionEntity is :
#Data
#Entity
#ToString(exclude = {"blackHole"})
#EqualsAndHashCode(exclude = "blackHole")
#Table(name = "vms_provider_blackhole_restriction")
public class VmsProviderRestrictionEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Enumerated(EnumType.STRING)
private OfferGradeConstant offerGrade;
#Convert(converter = CsvLongSetConverter.class)
#Column(name = "vms_restricted_providers", columnDefinition = "text")
private Set<Long> providerIds;
#ManyToOne
#JoinColumn(name = "blackhole_id")
private BlackholeDetailEntity blackHole;
}
PolygonDetailEntity.java
#MappedSuperclass
#Data
#ToString(exclude = {"master","masterPricing"})
#EqualsAndHashCode(callSuper = false, exclude = {"master", "masterPricing"})
public class PolygonDetailEntity extends ModifiableAuditableEntity {
private static final long serialVersionUID = -9100537914314976516L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "master_id")
private PolygonMasterEntity master;
#ManyToOne
#JoinColumn(name = "master_pricing_id")
private PolygonMasterPricingEntity masterPricing;
#Enumerated(EnumType.STRING)
private ProductType product;
private Integer serviceId;
#Column(columnDefinition = "text")
private String comments;
private String accessTechnology;
#Column(name = "is_active")
private Boolean active;
#Column(name = "is_deleted")
private Boolean deleted;
}

The abstract schema type 'User_Book' is unknown

I have a database with several entities, in particular Book and User. Between them there exists a ManyToMany relationship like this:
Book:
#Entity
#Table(name = "Books")
public class Book implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
#Column(name = "bookId", nullable = false, unique = true)
private Long id;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "price", nullable = false)
private int price;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "User_Book",
joinColumns = #JoinColumn(name = "bookId"),
inverseJoinColumns = #JoinColumn(name = "userId"))
private Set<UserAccount> users;
User:
#Entity
#Table(name = "UserAccounts")
public class UserAccount implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
#Column(name = "userId", nullable = false, unique = true)
private Long id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "password", nullable = false)
private String password;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "User_Book",
joinColumns = #JoinColumn(name = "userId"),
inverseJoinColumns = #JoinColumn(name = "bookId"))
Set<Book> purchasedBooks;
Everything works fine, the table User_Book is indeed created in the database. The problem seems to be related to the access of this Table.
For example,
Query query = entityManager.createQuery("SELECT u FROM User_Book u");
keeps telling me the following:
The abstract schema type 'User_Book' is unknown
So, shall I create from scratch the User_Book entity? Will it get automtically populated like now, that is, whenever a user buys a book, will this purchase be recorded in the table?
User_Book is not an entity. Therefore you cannot use createQuery, BUT you can use createNativeQuery to execute a SQL query:
Query query = entityManager.createNativeQuery("SELECT * FROM User_Book");
The result will be List<Object[]>

Deleting entity, which is element of collection and has collection of another entities in Hibernate

I have entity Ad:
#Entity
#NamedQueries({
#NamedQuery(name = "getAllAds",
query = "from Ad"),
#NamedQuery(name = "deleteById",
query = "delete from Ad where id = :id")
})
#FieldMatch(first = "initLanguage",second = "resultLanguage", message = "Languages must be different")
#Table(name = "AD_TEST")
public class Ad implements Serializable{
/**
* Version of this class in production
*/
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "standard", initialValue = 1)
#GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
#Column(name = "AD_ID")
private long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "CLIENT",nullable = false)
private Client client;
#NotBlank
#Column(name = "AD_NAME", nullable = false)
private String name;
#NotBlank
#Column(name = "AD_DESC",nullable = false,length = 1000)
#Lob
#Size(min = 0, max = 1000)
private String description;
#Column(name = "AD_COUNTRY", nullable = false)
private String country;
#Column(name = "AD_CITY", nullable = false)
private String city;
#NotNull
/**
* Добавить проверку валидности даты
*/
#DateTimeFormat(iso = ISO.DATE,pattern = "dd.MM.yyyy")
#Column(name = "AD_END_DATE",nullable = false)
private LocalDate endDate;
#NotNull
#Column(name = "AD_INIT_LANGUAGE",nullable = false)
#Enumerated(EnumType.STRING)
private Language initLanguage;
#NotNull
#Column(name = "AD_RESULT_LANGUAGE",nullable = false)
#Enumerated(EnumType.STRING)
private Language resultLanguage;
#NotNull
#Column(name = "AD_TRANSLATE_TYPE",nullable = false)
#Enumerated(EnumType.STRING)
private TranslateType translateType;
#Lob
#Column(name = "AD_FILE")
private byte[] file;
#NotNull
#Column(name = "AD_COST",nullable = false,precision = 2)
private double cost;
#NotNull
#Column(name = "AD_CURRENCY",nullable = false)
#Enumerated(EnumType.STRING)
private Currency currency;
#Column(name = "AD_CREATING_DATE",nullable = false)
private LocalDateTime creationDateTime;
#Column(name = "AD_STATUS",nullable = false)
#Enumerated(EnumType.STRING)
private AdStatus status;
#OnDelete(action = OnDeleteAction.CASCADE)
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "ad")
#Cascade(CascadeType.ALL)
private List<ResponsedAd> responsedAds = new ArrayList<>();
public Ad(){}
/*Getters and setters, hashCode and equals*/
Ad is element of collection in Client:
#Entity
#NamedQueries({
#NamedQuery(name = "clientByEmail",
query = "from Client client where client.email = :email")
})
#Table(name = "CLIENT_TEST")
#PrimaryKeyJoinColumn(name= "client_id")
public class Client extends User{
/**
* Version of this class in production
*/
private static final long serialVersionUID = 1L;
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
#Cascade(CascadeType.ALL)
public List<Ad> ads = new ArrayList<>();
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
#Cascade(CascadeType.ALL)
private List<ResponsedAd> responsedAds = new ArrayList<>();
public Client(){}
Ad.class and Client.class have collection of ResponseAd objects:
#Entity
#Table(name = "RESPONSED_AD_TEST")
#NamedQueries({
#NamedQuery(name = "responsedAdsByAd",query="from ResponsedAd where ad = :ad")
})
#Component
public class ResponsedAd {
#Id
#SequenceGenerator(name = "standard", initialValue = 1)
#GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
private long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "AD",nullable = false)
private Ad ad;
#Column(nullable = false)
private LocalDateTime dateTimeOfResponse;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "CLIENT")
private Client client;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "TRANSLATOR",nullable = false)
private Translator translator;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
private ResponsedAdStatus status;
public ResponsedAd(){}
I want that after deleting Ad object, all ResponseAd objects from collection were deleted too.
For this I have:
public void deleteById(long id){
Ad ad = get(id);
CopyOnWriteArrayList<ResponsedAd> list = new CopyOnWriteArrayList<>(ad.getResponsedAds());
list.forEach(rad->{
Translator translator = rad.getTranslator();
translator.removeResponsedAd(rad);
ad.removeResponsedAd(rad);
Client client = rad.getClient();
client.removeResponsedAd(rad);
});
Client client = ad.getClient();
client.removeAd(ad);
}
Say me please, how can I do this right? I have very a lot of relationships and when I try do this, I get error
HTTP Status 500 - Request processing failed; nested exception is
org.springframework.dao.InvalidDataAccessApiUsageException:
deleted object would be re-saved by cascade (remove deleted object from associations):
[ua.translate.model.ad.ResponsedAd#102]; nested exception is org.hibernate.ObjectDeletedException:
deleted object would be re-saved by cascade (remove deleted object from associations): [ua.translate.model.ad.ResponsedAd#102]
First of all,
You don't need to use #NotNull if you have nullable = false already declared in #Column(nullable = false).
Second,
What you're trying to do is doing operations in Cascade. Add this cascade = CascadeType.ALL or maybe cascade = CascadeType.REMOVE to your #ManyToOne tags and it should work.
Use this as a reference: JPA #ManyToOne with CascadeType.ALL
My Client object: Client client = rad.getClient(); have two responsedAd object in collection with the same id, therefore even after deleting this responsedAd object: client.removeResponsedAd(rad); client object has one more. And now main question is why this client have two objects with the same id.

Caused by: java.sql.SQLException: Column 'id' not found

I want to get some fields and then set it to my Test.entity. My SQL query:
query = "SELECT t.id as tId, t.test_name, t.duration, q.id as qId, " +
"q.question as question, q.is_multichoice as is_multichoice, " +
"q.is_open as is_open, a.id as aId, a.answer_text as answer_text FROM result r " +
"JOIN test t ON r.test_id = t.id " +
"JOIN user u ON r.user_id = u.id " +
"JOIN question q ON t.id = q.test_id JOIN answer a ON q.id = a.question_id " +
"WHERE t.id = :testId AND u.id = :userId AND r.permission = :permissionId " +
"AND q.archived = false AND a.archived = false", resultClass = com.bionic.entities.Test.class)
Test Entity:
public class Test {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "duration", nullable = false)
private int duration;
#Column(name = "test_name", nullable = false, unique = true)
private String testName;
#Column(name = "archived", nullable = false)
private boolean archived;
#OneToMany(mappedBy = "test", fetch = FetchType.EAGER)
private Set<Question> questions;
#ManyToMany(mappedBy = "tests")
private Set<User> users;
Question Entity:
public class Question {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "is_multichoice", nullable = false)
private boolean isMultichoice;
#Column(name = "is_open", nullable = false)
private boolean isOpen;
#Column(name = "picture")
private String picture;
#Column(name = "question")
private String question;
#ManyToOne
#JoinColumn(name = "test_id", nullable = false)
private Test test;
#Column(name = "archived", nullable = false)
private boolean isArchived;
#OneToMany(mappedBy = "question", fetch = FetchType.EAGER)
private Set<Answer> answers;
Answer Entity:
public class Answer {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "answer_text", nullable = false)
private String answerText;
#Column(name = "mark", nullable = false)
private int mark;
#ManyToOne
#JoinColumn(name = "question_id")
private Question question;
#Column(name = "picture")
private String picture;
#Column(name = "archived", nullable = false)
private boolean isArchived;
However, after executing this query i am getting exeption :
Caused by: java.sql.SQLException: Column 'id' not found.
DAO.class:
public Test getCurrentTest(long id, long testId, long permissionId) {
Query query = em.createNamedQuery("getCurrentTestById");
query.setParameter("userId", id);
query.setParameter("testId", testId);
query.setParameter("permissionId", permissionId);
return (Test) query.getSingleResult();
}
What am i doing wrong?
Your query doesn't return a field named id. It has fields named aId, qId, and tId.
You need to use the correct column names in your entities. For example, in your Test entity, you declared a column named id. Except your query doesn't return a column named id, it returns a column named tId. See below for an example of what needs to be changed.
public class Test {
#tId
#Column(name = "tId")
#GeneratedValue(strategy = GenerationType.AUTO)
private long tId;
....

Netbeans #JoinColoumns error with auto generated entity class

I've creating entities from a data-source using Netbeans 7.4.
And I have an error which arises with all entities which have a composite primary key. The error can be seen below.
I have searched this problem on stack-overflow and its is usually because people have not defined the join columns. but I have this done. I'm also unsure how there is errors in code generated by netbeans.
Here is an image of my MySQL database which I forward engineered to create these entitys:
Any help would be greatly appreciated !
Here is the only the relevant code
Absence entity:
public class Absence implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected AbsencePK absencePK;
#Basic(optional = false)
#NotNull
#Column(name = "idAbsence")
private int idAbsence;
#Basic(optional = false)
#NotNull
#Column(name = "Date")
#Temporal(TemporalType.DATE)
private Date date;
#Size(max = 35)
#Column(name = "type")
private String type;
#Lob
#Size(max = 65535)
#Column(name = "remark")
private String remark;
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Timetable timetable;
#JoinColumn(name = "Student_idStudent", referencedColumnName = "idStudent", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Student student;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
AbsencePK entity:
#Embeddable
public class AbsencePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
#Basic(optional = false)
#NotNull
#Column(name = "Student_idStudent")
private int studentidStudent;
#Basic(optional = false)
#NotNull
#Column(name = "TimeTable_Period")
private int timeTablePeriod;
public AbsencePK() {
}
public AbsencePK(int classidClass, int studentidStudent, int timeTablePeriod) {
this.classidClass = classidClass;
this.studentidStudent = studentidStudent;
this.timeTablePeriod = timeTablePeriod;
}
Error:
Caused by: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field timetable] from the entity class [class com.fyp.simstest.Absence] is incomplete.
When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns.
Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1847)
EDIT
TimeTable
#Entity
#Table(name = "timetable")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Timetable.findAll", query = "SELECT t FROM Timetable t"),
#NamedQuery(name = "Timetable.findByPeriod", query = "SELECT t FROM Timetable t WHERE t.timetablePK.period = :period"),
#NamedQuery(name = "Timetable.findByDay", query = "SELECT t FROM Timetable t WHERE t.timetablePK.day = :day"),
#NamedQuery(name = "Timetable.findByClassidClass", query = "SELECT t FROM Timetable t WHERE t.timetablePK.classidClass = :classidClass")})
public class Timetable implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TimetablePK timetablePK;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "timetable")
private Collection<Absence> absenceCollection;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
public Timetable() {
}
public Timetable(TimetablePK timetablePK) {
this.timetablePK = timetablePK;
}
TimetablePK
Embeddable
public class TimetablePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Period")
private int period;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "Day")
private String day;
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
public TimetablePK() {
}
public TimetablePK(int period, String day, int classidClass) {
this.period = period;
this.day = day;
this.classidClass = classidClass;
}
EDIT TWO
Your diagram indicates the TimeTable table has a primary key composed of three columns (Period, Day, and Class_idClass). You will need to add an annotation to Absence.timeTable that looks something like this:
public class Absence implements Serializable {
...
#JoinColumns[
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", ...),
#JoinColumn(name = "????", referencedColumnName = "Day", ...),
#JoinColumn(name = "Class_idClass", referencedColumnName = "Class_idClass", ...)
]
#ManyToOne(optional = false)
private TimeTable timeTable;
...
}
Consider this:
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period")
private Timetable timetable;
You have referenced to the column Period at your Timetable entity. But in the Timetable.java I don't see any field that is mapped with your Period column of your table.
For example:
#Id // as its the primary key!
#Column(name="Period")
private Long period
This should be same for other referenced entities those you have used with your #ManyToOne mapping.

Categories

Resources