delete query with where clause in HQL - java

I am new to hql and trying to delete the complete row in case of a match based on email.
Following is what I have tried.
Still I get a Persistence Exception.
public void unsubscribeEmailList(EmailListDto dataList) {
EmailList e =new EmailList(dataList);
Query q =sessionFactory.getCurrentSession().createQuery("delete from EmailList where email=:e");
q.setParameter("e", dataList);
int i=q.executeUpdate();
System.out.println(i);
}
Class EmailList is
#Entity
#Table(name = "email_list")
public class EmailList implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String email;
public EmailList(EmailListDto dto)
{
this.email=dto.getEmail();
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "email", nullable = false)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

Try use this:
q.setParameter("e", e.getEmail());

public void unsubscribeEmailList(EmailListDto dataList) {
EmailList e =new EmailList(dataList);
Query q =sessionFactory.getCurrentSession().createQuery("delete from EmailList where email = :e");
q.setParameter("e", e.egetEmail() );
int i=q.executeUpdate();
System.out.println(i);
}

...
#NamedQueries(
{
#NamedQuery(name = "FindAllJobsEngineersParticipateInInterval",
query = "SELECT je.id FROM Stage1JobEngineer AS je " +
"JOIN je.job AS s1j " +
"WHERE "
+ " :absenceStartDateTime <= :absenceEndDateTime "
+ " AND :absenceStartDateTime <= s1j.endTime AND :absenceEndDateTime >= s1j.startTime " +
" AND je.engineer.id IN (:engineerIds) ")
})
#Entity
#Table(name = "ho_stage1_job_has_engineers")
public class Stage1JobEngineer extends CreatedByUserEntity implements Serializable {
...
...
// dao service call :
Query query = getSession().getNamedQuery( "FindAllJobsEngineersParticipateInInterval" );
query.setParameter( "absenceStartDateTime", startDate )
.setParameter( "absenceEndDateTime", endDate )
.setParameterList( "engineerIds", Arrays.asList(1L, 2L, 33L) );
List<Long> queryResult = query.list();
List<Long> result = queryRes != null ? queryResult : new ArrayList<>();
...

Related

Managing both #NamedQueries and #NamedNativeQueries under the same Entity

I wanted to use anotations in order to keep the code clean but all I get are headaches.
I know the problem has to do with a column's name with an underscore as: rental_rate. If I used #NamedQuery, it is going to throw an error.
Here are the anotations
#Entity
#Table(name="film")
#NamedQueries({
#NamedQuery(name = "Film.findAll", query = "SELECT f FROM Film f")
,#NamedQuery(name = "Film.findById", query = "SELECT f FROM Film f WHERE f.filmId=:filmId")
,#NamedQuery(name = "Film.ratings", query = "SELECT f.rating FROM Film f")
,#NamedQuery(name = "Film.prices", query = "SELECT f.rental_rate FROM Film f")
})
The anotation that I am struggling with is:
#NamedQuery(name = "Film.prices", query = "SELECT f.rental_rate FROM Film f")
it throws this error which I believe it has to do with the underscore in the column's name.
Caused by: org.hibernate.HibernateException: Errors in named queries: Film.prices
After some research I found about #NamedNativeQuery in this question and so I decided to change the anotation to:
#Entity
#Table(name="film")
#NamedQueries({
#NamedQuery(name = "Film.findAll", query = "SELECT f FROM Film f")
,#NamedQuery(name = "Film.findById", query = "SELECT f FROM Film f WHERE f.filmId=:filmId")
,#NamedQuery(name = "Film.ratings", query = "SELECT f.rating FROM Film f")
//,#NamedQuery(name = "Film.prices", query = "SELECT f.rental_rate FROM Film f")
})
#NamedNativeQueries({
#NamedNativeQuery(name = "Film.prices", query = "SELECT f.rental_rate FROM Film f")
})
but then it would be outside the Entity
Caused by: org.hibernate.MappingException: Unknown entity: java.lang.String
How can I manage this issue?
NOTES
Java 8
Netbeans 11
JPA (Hibernate 4.3.1)
EDIT
Full class file
#Entity
#Table(name="film")
#NamedQueries({
#NamedQuery(name = "Film.findAll", query = "SELECT f FROM Film f")
,#NamedQuery(name = "Film.findById", query = "SELECT f FROM Film f WHERE f.filmId=:filmId")
,#NamedQuery(name = "Film.ratings", query = "SELECT f.rating FROM Film f")
,#NamedQuery(name = "Film.prices", query = "SELECT f.rentalRate FROM Film f")
})
/*#NamedNativeQueries({
#NamedNativeQuery(name = "Film.prices", query = "SELECT f.rentalRate FROM Film f")
})*/
public class Film implements Serializable{
#Id
private int filmId;
private String title;
private String Description;
private String releaseYear;
#NaturalId
private int languageId;
#NaturalId
#Column(nullable=true)
private Integer originalLanguageId;
private int rentalDuration;
private float rentalRate;
private int length;
private float replacementCost;
private String rating;
private String specialFeatures;
private Timestamp lastUpdate;
#ManyToMany(cascade = CascadeType.ALL , fetch = FetchType.EAGER)
#JoinTable(
name = "film_category",
joinColumns = { #JoinColumn(name = "film_id") },
inverseJoinColumns = { #JoinColumn(name = "category_id") }
)
private Set<Category> categories = new HashSet<Category>();
#ManyToMany(cascade = CascadeType.ALL , fetch = FetchType.EAGER)
#JoinTable(
name = "inventory",
joinColumns = { #JoinColumn(name = "film_id") },
inverseJoinColumns = { #JoinColumn(name = "inventory_id") }
)
private List<Store> stores = new ArrayList<Store>();
public int getFilmId() {
return filmId;
}
public void setFilmId(int filmId) {
this.filmId = filmId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return Description;
}
public void setDescription(String Description) {
this.Description = Description;
}
public String getReleaseYear() {
return releaseYear;
}
public void setReleaseYear(String releaseYear) {
this.releaseYear = releaseYear;
}
public int getLanguageId() {
return languageId;
}
public void setLanguageId(int languageId) {
this.languageId = languageId;
}
public int getOriginalLanguageId() {
return originalLanguageId;
}
public void setOriginalLanguageId(int originalLanguageId) {
this.originalLanguageId = originalLanguageId;
}
public int getRentalDuration() {
return rentalDuration;
}
public void setRentalDuration(int rentalDuration) {
this.rentalDuration = rentalDuration;
}
public float getRentalRate() {
return rentalRate;
}
public void setRentalRate(float rentalRate) {
this.rentalRate = rentalRate;
}
public int getLenght() {
return length;
}
public void setLenght(int lenght) {
this.length = lenght;
}
public float getReplacementCost() {
return replacementCost;
}
public void setReplacementCost(float replacementCost) {
this.replacementCost = replacementCost;
}
public String getRating() {
return rating;
}
public void setRating(String rating) {
this.rating = rating;
}
public String getSpecialFeatures() {
return specialFeatures;
}
public void setSpecialFeatures(String specialFeatures) {
this.specialFeatures = specialFeatures;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Timestamp getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Timestamp lastUpdate) {
this.lastUpdate = lastUpdate;
}
public void setCategories(Set<Category> categories) {
this.categories = categories;
}
public Set<Category> getCategories() {
return this.categories;
}
public List<Store> getStores() {
return stores;
}
public void setStores(List<Store> stores) {
this.stores = stores;
}
#Override
public String toString() {
return "Film{" + "filmId=" + filmId + ", title=" + title + ", Description=" + Description + ", releaseYear=" + releaseYear + ", languageId=" + languageId + ", originalLanguageId=" + originalLanguageId + ", rentalDuration=" + rentalDuration + ", rentalRate=" + rentalRate + ", length=" + length + ", replacementCost=" + replacementCost + ", rating=" + rating + ", specialFeatures=" + specialFeatures + ", lastUpdate=" + lastUpdate + ", categories=" + categories + '}';
}
}
You should test if the attribute in File class is something like rentalRate not rental_rate
So in JPA, we use the attributes' names from the class not the columns' names in Database
Update your entity class and use #Column annotation with the name in the database and you can use any name related to java convention and use it in JPA
Check if your id is auto increment use #GeneratedValue annotation if not like PostgreSQL use this one where name_seq is the sequence name
#SequenceGenerator(name="name_seq",
sequenceName="name_seq",
allocationSize=1)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator="name_seq")
, Entity
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int filmId;
#Column(name="title")
private String title;
#Column(name="description")
private String Description;
#Column(name="release_year")
private String releaseYear;
#NaturalId
private int languageId;
#NaturalId
#Column(name="original_languageId", nullable=true)
private Integer originalLanguageId;
#Column(name="rental_duration")
private int rentalDuration;
#Column(name="rental_rate")
private float rentalRate;
#Column(name="length")
private int length;
#Column(name="replacement_cost")
private float replacementCost;
#Column
private String rating;
#Column(name="special_features")
private String specialFeatures;
#Column(name="last_update")
private Timestamp lastUpdate;
Update the query to match the attribute names in the Film class, like this:
#Entity
#Table(name="film")
#NamedQueries({
#NamedQuery(name = "Film.findAll", query = "SELECT f FROM Film f")
,#NamedQuery(name = "Film.findById", query = "SELECT f FROM Film f WHERE f.filmId=:filmId")
,#NamedQuery(name = "Film.ratings", query = "SELECT f.rating FROM Film f")
,#NamedQuery(name = "Film.prices", query = "SELECT f.rentalRate FROM Film f")
})

How to display hibernate search results using QueryBuilder, Lucene Query & FullTextQuery?

How to display results using FullTextEntity Manager with order clause only.
EntityManager em = factory.createEntityManager();
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity( Desh.class ).get();
org.apache.lucene.search.Query query = new org.apache.lucene.search.MatchAllDocsQuery();
//Also used qb.all().getQuery(); but no results
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, Desh.class);
System.out.println(""+ query);
System.out.println(""+ query.toString());
fullTextQuery.setSort(new Sort(new SortField("DeshName_for_sort", SortField.STRING, true)));
//Also used DESH but no results
fullTextQuery.setFirstResult(0).setMaxResults(60);
System.out.println("" + fullTextQuery);
System.out.println("" + fullTextQuery.getParameters());
int size = fullTextQuery.getResultSize();
List<Desh> result = fullTextQuery.getResultList();
System.out.println("Size e -> "+ size);
System.out.println("Size e -> "+ result.size());
for (Deshuser : result) {
System.out.println("Id: " + user.getId());
System.out.println("Person Id:" + user.getName());
}
Desh - Entity Class:
#Entity
#Table(name = "DESH")
#XmlRootElement
#Indexed
public class Desh implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "ID")
private Long id;
#Fields({ #Field(index = Index.YES, store = Store.NO), #Field(name = "DeshName_for_sort", index = Index.YES, analyze = Analyze.NO) })
#Column(name = "NAME", length = 100)
private String name;
public Desh () {
}
public Desh (Long id) {
this.id = id;
}
public Desh (Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "in.hibprac.hibernatepractice.Desh[ id=" + id + " ]";
}
}
When i run above program, it returns no size. But when i return using Namedquery and Native Query it executes fine. Even when i remove sorting statements in code, it returns nothing. Could anyone guide me where the problem is?
try this :
FullTextEntityManager ftem=Search.getFullTextEntityManager(entityManager);
ftem.createIndexer().startAndWait();
to launch an indexation targetting all entities annotated with #Indexed

How to make a query using columns of a JoinTable in Rest Webservice with netbeans

How I can to do this query:
#NamedQuery(name = "Scuser.findFriends", query = "SELECT s FROM Scuser s, friends f WHERE f.firstid = :iduser and s.iduser = f.secondid")
in this class:
#Entity
#Table(name = "scuser")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Scuser.findAll", query = "SELECT s FROM Scuser s"),
#NamedQuery(name = "Scuser.findByIduser", query = "SELECT s FROM Scuser s WHERE s.iduser = :iduser"),
#NamedQuery(name = "Scuser.findByUpassword", query = "SELECT s FROM Scuser s WHERE s.upassword = :upassword"),
#NamedQuery(name = "Scuser.findByUname", query = "SELECT s FROM Scuser s WHERE s.uname = :uname"),
#NamedQuery(name = "Scuser.findByTpoints", query = "SELECT s FROM Scuser s WHERE s.tpoints = :tpoints"),
// #NamedQuery(name = "Scuser.findFriends", query = "SELECT s FROM Scuser s, friends f WHERE f.firstid = :iduser and s.iduser = f.secondid"),
#NamedQuery(name = "Scuser.findByUnameUpassword", query = "SELECT s FROM Scuser s WHERE s.uname = :uname and s.upassword = :upassword")})
public class Scuser implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 2147483647)
#Column(name = "iduser")
private String iduser;
#Size(max = 200)
#Column(name = "upassword")
private String upassword;
#Size(max = 200)
#Column(name = "uname")
private String uname;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "tpoints")
private Double tpoints;
#JoinTable(name = "friends", joinColumns = {
#JoinColumn(name = "firstid", referencedColumnName = "iduser")}, inverseJoinColumns = {
#JoinColumn(name = "secondid", referencedColumnName = "iduser")})
#ManyToMany
private Collection<Scuser> scuserCollection;
#ManyToMany(mappedBy = "scuserCollection")
private Collection<Scuser> scuserCollection1;
#ManyToMany(mappedBy = "scuserCollection")
private Collection<Beach> beachCollection;
public Scuser() {
}
public Scuser(String iduser) {
this.iduser = iduser;
}
public String getIduser() {
return iduser;
}
public void setIduser(String iduser) {
this.iduser = iduser;
}
public String getUpassword() {
return upassword;
}
public void setUpassword(String upassword) {
this.upassword = upassword;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Double getTpoints() {
return tpoints;
}
public void setTpoints(Double tpoints) {
this.tpoints = tpoints;
}
#XmlTransient
public Collection<Scuser> getScuserCollection() {
return scuserCollection;
}
public void setScuserCollection(Collection<Scuser> scuserCollection) {
this.scuserCollection = scuserCollection;
}
#XmlTransient
public Collection<Scuser> getScuserCollection1() {
return scuserCollection1;
}
public void setScuserCollection1(Collection<Scuser> scuserCollection1) {
this.scuserCollection1 = scuserCollection1;
}
#XmlTransient
public Collection<Beach> getBeachCollection() {
return beachCollection;
}
public void setBeachCollection(Collection<Beach> beachCollection) {
this.beachCollection = beachCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (iduser != null ? iduser.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 Scuser)) {
return false;
}
Scuser other = (Scuser) object;
if ((this.iduser == null && other.iduser != null) || (this.iduser != null && !this.iduser.equals(other.iduser))) {
return false;
}
return true;
}
#Override
public String toString() {
return "REST.Scuser[ iduser=" + iduser + " ]";
}
}
If I understand correctly, you have the ID of a user, and you want to get the friends of the user identified by this ID. The easiest way is to do
Scuser user = em.find(User.class, userId);
Collection<Scuser> friends = user.getScuserCollection();
If you want to do it using a JPQL query, you just need
select friend from Scuser user
inner join user.scuserCollection friend
where user.id = :userId
Note that your mapping isn't right: scuserCollection1 and beachCollection are both mapped by the same attribute. You should also choose better names for your associations (like friends for example, instead of scuserCollection).

How do I update multiple tables inside a named query?

I am using Eclipselink v2.3.3
I am getting this error
Error compiling the query [Credential.updateExistingCredentialNoPW: UPDATE Credential c SET c.active = :active, c.employee.address.streetAddress = :stadd, c.employee.address.city = :city, c.employee.address.province = :prov, c.employee.address.zip = :zip WHERE c.id = :id], line 1, column 46: invalid navigation expression [c.employee], cannot navigate association field [employee] in the SET clause target.
when I try to run my code.
Here are the affected named queries that prevents running my code
#NamedQuery(name = "Credential.updateExistingCredentialNoPW",
query = "UPDATE Credential c "
+ "SET c.active = :active, "
+ "c.employee.address.streetAddress = :stadd, "
+ "c.employee.address.city = :city, "
+ "c.employee.address.province = :prov, "
+ "c.employee.address.zip = :zip "
+ "WHERE c.id = :id"),
#NamedQuery(name = "Credential.updateExistingCredential",
query = "UPDATE Credential c "
+ "SET c.password = :pw, "
+ "c.active = :active, "
+ "c.employee.address.streetAddress = :stadd, "
+ "c.employee.address.city = :city, "
+ "c.employee.address.province = :prov, "
+ "c.employee.address.zip = :zip "
+ "WHERE c.id = :id"),
#NamedQuery(name = "Credential.updateSalary",
query = "UPDATE Credential c "
+ "SET c.employee.salary.value = :val WHERE c.id = :id")
Here is the class where I put all the named queries specified above
public class Credential implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator = "CRED_GEN", strategy = GenerationType.IDENTITY)
#Column(name = "CREDENTIAL_ID")
private long id;
// unique & not nullabe username
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false, name = "USER_KEY")
private String password;
#Column(nullable = false)
private boolean active;
#Column(nullable = false)
private int userLevel;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Employee employee;
public Credential() {
}
public Credential(String username, String password, boolean active,
int userLevel, Employee employee) throws NoSuchAlgorithmException {
this.username = username;
this.setPassword(password);
this.active = active;
this.userLevel = userLevel;
this.employee = employee;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getUserLevel() {
return userLevel;
}
public void setUserLevel(int userLevel) {
this.userLevel = userLevel;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getPassword() {
return password;
}
public void setPassword(String password) throws NoSuchAlgorithmException {
this.password = Cryptography.getHash(password);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
Am I doing it wrong?
It is not possible to update multiple tables with single sql query.
See https://forums.oracle.com/forums/thread.jspa?threadID=2223393.
So it's also not possible with Eclipselink.
You'll have to split this it two queries, or better use setters.
You can't. Either use a SQL query, or use Java code:
Credential c = em.find(Credential.class, credentialId);
c.setActive(active);
c.getEmployee().getAddress().setStreet(street);
...

Hibernate - fetch only the latest versions of elements in contained collection

I have an entity :
#Entity
#DiscriminatorValue("News")
public class News extends TVProduction {
private int audience;
private Collection<Reportage> reportages;
public News() {
super();
setAudience(0);
}
#Column(name = "audience")
public int getAudience() {
return audience;
}
public void setAudience(int audience) {
this.audience = audience;
}
#OneToMany
#JoinTable(name = "Reportages_News",
joinColumns = #JoinColumn(name = "news_id"),
inverseJoinColumns = #JoinColumn(name = "reportage_id")
)
public Collection<Reportage> getReportages() {
return reportages;
}
public void setReportages(Collection<Reportage> reportages) {
this.reportages = reportages;
}
}
And Reportage class looks like this:
#Entity
#Table(name = "Reportage")
public class Reportage {
private Long id;
private String subject;
private int version;
private String content;
private Reporter reporter;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
#SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name = "reporter_fk")
public Reporter getReporter() {
return reporter;
}
public void setReporter(Reporter reporter) {
this.reporter = reporter;
}
}
What I want is to have only the highest versions of Reportages fetched while fetching News. I tried to annotate Reportage with:
#Loader(namedQuery = "fetchFinal")
#NamedNativeQuery(name = "fetchFinal", query = "SELECT t.* FROM" +
"(SELECT id, subject, max(version) maxVersion, content, reporter" +
"FROM reportage GROUP BY id) x" +
"JOIN reportage t ON x.id = t.id AND x.maxVersion = t.version AND t.id = ?"
)
but It doesn't work, saying:
Initial SessionFactory creation failed.org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported
Any idea how to get it done?
How about:
select * from reportage t where t.version = (select max(t2.version) from reportage t2)
UPDATE:
Have not tried this myself:
#NamedNativeQuery(name = "fetchFinal", query = "SELECT t.* FROM" +
"(SELECT id, subject, max(version) maxVersion, content, reporter" +
"FROM reportage GROUP BY id) x" +
"JOIN reportage t ON x.id = t.id AND x.maxVersion = t.version AND t.id = ?",
resultClass=Reportage.class)
= add Resultclass
UPDATE2
If that doesn't work this certainly will (since I've done this myself); using Criteria:
Criteria crit = getSession().createCriteria(Reportage.class);
DetachedCriteria dc = DetachedCriteria.forClass(Reportage.class);
dc.setProjection(Projections.max("version"));
crit.add(Property.forName("version").eq(dc));
return crit.list();

Categories

Resources