This is my DUsers class:
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.Date;
import java.util.Objects;
#Entity
#Table(name = "d_users")
#NamedQueries({
#NamedQuery(name = "bonsai.dropwizard.dao.d.DUsers.findAll",
query = "select e from DUsers e"),
#NamedQuery(name = "bonsai.dropwizard.dao.d.DUsers.findById",
query = "select e from DUsers e "
+ "where e.oAuthId = :id "),
#NamedQuery(name = "bonsai.dropwizard.dao.d.DUsers.findByOAuthId",
query = "select e from DUsers e "
+ "where e.oAuthId = :oAuthId "),
#NamedQuery(name = "bonsai.dropwizard.dao.d.DUsers.findByEmail",
query = "select e from DUsers e "
+ "where e.email = :email "),
#NamedQuery(name="bonsai.dropwizard.dao.d.DUsers.confirm",
query = "update DUsers set status = 'HELLO' where oAuthId = :id")
})
public class DUsers implements IDdbPojo{
#Id
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
private String oAuthId;
private String oAuthType;
private String firstName;
private String secondName;
private String city;
private String phone;
private String email;
private String profileLink;
private String profilePic;
private String status;
private String notificationToken;
private boolean confirmed;
private String password;
private String notes;
private java.util.Date created_timestamp;
private java.util.Date updated_timestamp;
.. getters and setters on-going
As you can see, I have defined a few #NamedQueries and they all work properly except the last one that needs to update my database. In order to run this query, I defined two functions:
private void confirmMailDAO(String id) {
namedQuery("bonsai.dropwizard.dao.d.DUsers.confirm").setParameter("id", id);
}
public void confirmMailInternal(String id) {
Session session = sessionFactory.openSession();
try{
ManagedSessionContext.bind(session);
Transaction transaction = session.beginTransaction();
try{
confirmMailDAO(id);
transaction.commit();
}catch (Exception e) {
transaction.rollback();
throw new RuntimeException(e);
}
} finally {
session.close();
ManagedSessionContext.unbind(sessionFactory);
}
}
After this I defined a path followed by a POST request that should update my database but sadly it doesn't.
#POST
#Path("/confirm/{id}")
public void confirmMail(#NotNull #PathParam("id") String id){
DUsers user = AppConfig.getInstance().getdUsersDAO().findByIdInternal(id);
if (user == null) {
throw new NotAuthorizedException("Error");
}
AppConfig.getInstance().getdUsersDAO().confirmMailInternal(id);
}
Does anyone know where am I getting wrong?
You have set param in named query but forgot to execute it.
Pass session to your method and execute like:
private void confirmMailDAO(Session session, String id) {
Query query = session.getNamedQuery("bonsai.dropwizard.dao.d.DUsers.confirm").setParameter("id", id);
query.executeUpdate();
}
Related
I have a Java RESTapi, where I want to convert a list of my custom Pet object into Json, and display it in an endpoint.
This I what I have so far:
#Path("/allPets")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() {
List<Pet> petList = new ArrayList<>();
petList.addAll(facade.returnAllPets());
String json = gson.toJson(petList);
//TODO return proper representation object
return Response.ok().entity(json).build();
}
I'm using the facade pattern where I have a method of adding Java entities to a list as such:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PetHospitaljpa");
public Collection<Pet> returnAllPets (){
EntityManager em = emf.createEntityManager();
//vi laver en typed query for at specificere hvilken datatype,
// det er vi leder efter, i dette tilfælde er det en Pet
TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
return query.getResultList();
}
I'm returning a collection in case I want to change the data structure of ArrayList to something else later.
I have tried several workarounds, but I keep getting a stack overflow error.
Iøm aware of the fact, that I need to use DTO's instead, and I have made a custom method to change entities to DTO's as such:
public static DTOPet converttoDTO(Pet entity){
DTOPet dto = new DTOPet();
dto.setId(entity.getId());
dto.setName(entity.getName());
dto.setBirth(entity.getBirth());
dto.setDeath(entity.getDeath());
dto.setSpecies(entity.getSpecies());
return dto;
}
I'm not sure if this is good code practice if I there is something else I can do instead to transform a collection of entities into DTO's?
As pointed out. The problem occurs because I have a circular reference.
inside my Pet Entity class:
#ManyToOne
private Owner ownerId;
inside my Owner Entity class:
#OneToMany(mappedBy = "ownerId")
private Collection<Pet> petCollection;
My Pet Class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Entities;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
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.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author kristoffer
*/
#Entity
#Table(name = "pet")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Pet.findAll", query = "SELECT p FROM Pet p")
, #NamedQuery(name = "Pet.findById", query = "SELECT p FROM Pet p WHERE p.id = :id")
, #NamedQuery(name = "Pet.findByName", query = "SELECT p FROM Pet p WHERE p.name = :name")
, #NamedQuery(name = "Pet.findByBirth", query = "SELECT p FROM Pet p WHERE p.birth = :birth")
, #NamedQuery(name = "Pet.findBySpecies", query = "SELECT p FROM Pet p WHERE p.species = :species")
, #NamedQuery(name = "Pet.findByDeath", query = "SELECT p FROM Pet p WHERE p.death = :death")})
public class Pet implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "name")
private String name;
#Basic(optional = false)
#NotNull
#Column(name = "birth")
#Temporal(TemporalType.DATE)
private Date birth;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "species")
private String species;
#Column(name = "death")
#Temporal(TemporalType.DATE)
private Date death;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "petId")
private Collection<Event> eventCollection;
#JoinColumn(name = "owner_id", referencedColumnName = "id")
#ManyToOne
private Owner ownerId;
public Pet() {
}
public Pet(Integer id) {
this.id = id;
}
public Pet(Integer id, String name, Date birth, String species) {
this.id = id;
this.name = name;
this.birth = birth;
this.species = species;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
public Date getDeath() {
return death;
}
public void setDeath(Date death) {
this.death = death;
}
#XmlTransient
public Collection<Event> getEventCollection() {
return eventCollection;
}
public void setEventCollection(Collection<Event> eventCollection) {
this.eventCollection = eventCollection;
}
public Owner getOwnerId() {
return ownerId;
}
public void setOwnerId(Owner ownerId) {
this.ownerId = ownerId;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Pet)) {
return false;
}
Pet other = (Pet) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Pet{" + "id=" + id + ", name=" + name + ", birth=" + birth + ", species=" + species + ", death=" + death + ", eventCollection=" + eventCollection + ", ownerId=" + ownerId + '}';
}
}
EDIT:
I tried creating a method, where I convert all the objects to DTO's, but the string is still empty when it is displayed:
#Path("/allPets")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() {
//med denne metode skal vi bruge et DTO(data transfer object til at formatere til Json)
List<Pet> petList = new ArrayList<>();
List<DTOPet> DTOPetList = new ArrayList<>();
petList.addAll(facade.returnAllPets());
for(Pet pet: petList){
DTOPet dtopet = EntitytoDTO.converttoDTO(pet);
DTOPetList.add(dtopet);
}
String json = gson2.toJson(DTOPetList);
return Response.ok().entity(json).build();
}
When I use the debugger, the new list is created successfully, with the right parameters, but the String JSON is just created like this [{},{},{},{}], even though I use GSON
You need to detect what place of error. I recommend to add debug information, like
#Path("/allPets")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() {
log.debug("getPetsfromCollection start");
List<Pet> petList = new ArrayList<>(facade.returnAllPets());
log.debug("petList" + petList.length());
String json = gson.toJson(petList);
log.debug("json " + json);
//TODO return proper representation object
return Response.ok().entity(json).build();
}
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PetHospitaljpa");
public Collection<Pet> returnAllPets (){
log.debug("returnAllPets start");
EntityManager em = emf.createEntityManager();
log.debug("createNamedQuery start");
TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
log.debug("single result" + query.getSingleResult() );
TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
log.debug("list result" + query.getResultList());
TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
return query.getResultList();
}
P.S. Also, please show Pet class, may be problem is with this class.
Update: I recommend also to try temporary delete:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "petId")
private Collection<Event> eventCollection;
And / or
#JoinColumn(name = "owner_id", referencedColumnName = "id")
#ManyToOne
private Owner ownerId;
And check do you have such SO exception or not. It is look like Event or Owner table is too big or have circle dependencies.
Without seeing what the "Pet" class looks like, it is difficult to pinpoint the problem. I suspect you have a variable of another class in your Pet class that also has a reference to the pet class itself (creating a circular reference that would cause a stack overflow in the serialization process)
This question What is the right way to use entitymanager
supplied a link to EntityManagerHelper.java which I added to my code base. When I use this helper class to make subsequent calls to the database it returns previous results to the same query.
The scenario I see this most in is retrieving the lastentry property of my User Class. On the browser I make an AJAX request and the servlet partial below gets the user object and calls a method to return my lastentry.
I've read about .clear() but I get server errors when I added it to my EntityManagerHelper. I would like to avoid creating an EntityManager every time I want to make a call to the db.
How can I fix this problem?
partial from servlet
User user = User.getUser();
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(user.getLastentry());
User Class
package entities;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Persistence;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.shiro.SecurityUtils;
import responseablees.EntityManagerHelper;
/**
*
* #author Christopher Loughnane <chrisloughnane1#gmail.com>
*/
#Entity
#Table(name = "user")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
, #NamedQuery(name = "User.findById", query = "SELECT u FROM User u WHERE u.id = :id")
, #NamedQuery(name = "User.findByUsername", query = "SELECT u FROM User u WHERE u.username = :username")
, #NamedQuery(name = "User.getUsernameByUserEmail", query = "SELECT u.username FROM User u WHERE u.useremail = :useremail")
, #NamedQuery(name = "User.findByUserEmail", query = "SELECT u FROM User u WHERE u.useremail = :useremail")
, #NamedQuery(name = "User.findByPassword", query = "SELECT u FROM User u WHERE u.password = :password")})
public class User implements Serializable {
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 2048)
#Column(name = "lastentry")
private String lastentry;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 128)
#Column(name = "useremail")
private String useremail;
#Basic(optional = false)
#Column(name="created", insertable = false, updatable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date created;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(name = "username")
private String username;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(name = "password")
private String password;
public User() {
}
public User(Integer id) {
this.id = id;
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 User)) {
return false;
}
User other = (User) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "DAOs.User[ id=" + id + " ]";
}
public String getUseremail() {
return useremail;
}
public void setUseremail(String useremail) {
this.useremail = useremail;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getLastentry() {
return lastentry;
}
public void setLastentry(String lastentry) {
this.lastentry = lastentry;
}
public static User getUser(){
String currentUser = (String) SecurityUtils.getSubject().getPrincipal();
User user = (User) em.createNamedQuery("User.findByUserEmail")
.setParameter("useremail", currentUser)
.getSingleResult();
return user;
}
}
Requested Code
Verbose Approach
String currentUser = (String) SecurityUtils.getSubject().getPrincipal();
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("com.mycompany_responseableES_war_1.0-SNAPSHOTPU");
EntityManager em = emfactory.createEntityManager();
User user = (User) em.createNamedQuery("User.findByUserEmail")
.setParameter("useremail", currentUser)
.getSingleResult();
em.getTransaction().begin();
user.setLastentry(JSON);
em.getTransaction().commit();
EntityManagerHelper Approach
User user = User.getUser();
EntityManager em = EntityManagerHelper.getEntityManager();
em.getTransaction().begin();
user.setLastentry(JSON);
em.getTransaction().commit();
First of all, I would be careful to put ALL my data fetching/modification code between
em.getTransaction().begin()
and
em.getTransaction().commit()
This ensures that your entities are managed and your changes are automatically persisted. In your code it looks like the User instance comes from outside the transaction. I have not worked much with JPA and manual transactions, but I would not be surprised if the user is detached (that is, not managed by the EntityManager) and so changes are not automatically persisted to the database. If that were the case I guess you could solve it by putting
// merge(...) takes an entity that is not managed, apply changes to
// the persistence context and returns a new *managed* entity.
// The original entity REMAINS *detached* or *non persistent*
User managedUser = em.merge(user);
// I assume that you have something like this to set your user in the
// current session or whatever
User.setUser(managedUser);
just before the commit.
JPA vocabulary can be a bit hard at first, read this for more details about the JPA entity lifecycle (specially the diagram at the bottom).
I have the following problem, in my application I would like to have some kind of login. I have following code: (Inspiration here on the web)
public boolean login(String username, String password)
{
try{
EntityTransaction entr=em.getTransaction();
entr.begin();
TypedQuery<Users> query = em.createQuery("SELECT u FROM users u WHERE u.login = :login AND u.password = :pass", Users.class);
query.setParameter(1, username);
query.setParameter(2, password);
try{
Users u = query.getSingleResult();
return true;
}catch(javax.persistence.NoResultException e)
{
return false;
}
}
finally{
em.close();
}
}
When I run it and try to log in, the console will write the following message:
exception in thread "main" java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT u FROM users u WHERE u.login = :login AND u.password = :pass].
[14, 19] The abstract schema type 'users' is unknown.
[28, 35] The state field path 'u.login' cannot be resolved to a valid type.
[49, 59] The state field path 'u.password' cannot be resolved to a valid type.
This is my table:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.dke.ps.Tables;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
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.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author michal
*/
#Entity
#Table(name = "users")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u")
, #NamedQuery(name = "Users.findByUserid", query = "SELECT u FROM Users u WHERE u.userid = :userid")
, #NamedQuery(name = "Users.findByLogin", query = "SELECT u FROM Users u WHERE u.login = :login")
, #NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")
, #NamedQuery(name = "Users.findByEmail", query = "SELECT u FROM Users u WHERE u.email = :email")
, #NamedQuery(name = "Users.findByDate", query = "SELECT u FROM Users u WHERE u.date = :date")})
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "userid")
private Integer userid;
#Column(name = "login")
private String login;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "date")
#Temporal(TemporalType.DATE)
private Date date;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userid")
private Collection<Saves> savesCollection;
#JoinColumn(name = "saveid", referencedColumnName = "saveid")
#ManyToOne
private Saves saveid;
public Users() {
}
public Users(Integer userid) {
this.userid = userid;
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#XmlTransient
public Collection<Saves> getSavesCollection() {
return savesCollection;
}
public void setSavesCollection(Collection<Saves> savesCollection) {
this.savesCollection = savesCollection;
}
public Saves getSaveid() {
return saveid;
}
public void setSaveid(Saves saveid) {
this.saveid = saveid;
}
#Override
public int hashCode() {
int hash = 0;
hash += (userid != null ? userid.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 Users)) {
return false;
}
Users other = (Users) object;
if ((this.userid == null && other.userid != null) || (this.userid != null && !this.userid.equals(other.userid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.dke.ps.Tables.Users[ userid=" + userid + " ]";
}
}
As you can see, the "users" table really exists. I have no idea why it says to me, "The abstract schema type 'users' is unknown.".
Can you help me? I think the other two errors are caused by the first one.
This exception relates to JPQL query compiling, JPQL syntax expect entity names instead table names, try changing your query to the following:
SELECT u FROM **Users** u WHERE u.login = :login AND u.password = :pass
I have an Entity (persisted on mongodb) called SourceCondition with property workflowID and I want to delete all SourceCondition objects with a particular workflowID.
The entity is:
#Entity
#Table(name="source_conditions")
public class SourceCondition {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#TableGenerator(
name = "source_conditions"
)
private ObjectId id;
public String getId() { return id.toString(); }
public void setId(ObjectId id) { this.id = id; }
#Column(name="workflowID")
private String workflowID;
public SourceCondition() {}
public String getWorkflowID() {
return workflowID;
}
public void setWorkflowID(String workflowID) {
this.workflowID = workflowID;
}
}
The query I execute is:
Session s = HibernateUtil.getSessionFactory().openSession();
Query query = s.createQuery("delete from SourceCondition where workflowID = :wid");
query.setParameter("wid", "sampleID");
int result = query.executeUpdate();
I receive the following error:
Syntax error in query: [delete from com.backend.Models.Source.SourceCondition where workflowID = :wid]
I also tried with:
Query query = s.createQuery("delete SourceCondition where workflowID = :wid");
query.setParameter("wid", "sampleID");
int result = query.executeUpdate();
but I receive the same error.
=====================
EDIT
I bypass the problem with:
Query query1 = s.createQuery("from SourceCondition sc where sc.workflowID = :wid");
query1.setParameter("wid", "sampleID");
List l1 = query1.list();
Iterator<?> it1 = l1.iterator();
while (it1.hasNext())
{
SourceCondition sc = (SourceCondition) it1.next();
s.delete(sc);
s.flush();
}
It is not the best way to achieve deletion, but it works at the moment.
You need to give the SourceCondition a variable name:
delete from SourceCondition sc where sc.workflowID = :wid
I have a problem regarding jpa query.
There are two tables i.e. Post table and Tag table
There is many to many relationship between Post and Tag
Now I want to write a query such that when multiple tags are chosen then all the posts associated with those tags should be selected.
For example,
post1 has tags friends and motivation
post2 has tags motivation and pune
post3 has tag boxing
if tags friends and pune are chosen then post1 and post 2 should be retrieved
if tag boxing is chosen then only post 3 should be retrieved
if tags boxing and motivation are chosen then all three posts should be retrieved.
I tried following things
SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags IN :tags
but it gives validator error that
The state field path 'p.tags' cannot be resolved to a collection type.
If I try like this
SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags = :tags
then it complies fine but after passing a list of tags it gives error
java.lang.IllegalArgumentException: You have attempted to set a value of type class java.util.ArrayList for parameter tags with expected type of class com.justme.model.entities.Tag from query string SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags = :tags.
Thank you for reading this much :) can you please guide me on this?
how can I achieve the results mentioned above?
my persistence provider is eclipseLink
This is Post entity
#Entity
#NamedQueries({
#NamedQuery(name = "Post.selectAllPosts", query = "SELECT p FROM Post p ORDER BY p.dateCreated DESC"),
#NamedQuery(name = "Post.selectPostForUser", query = "SELECT p FROM Post p WHERE p.user = :user ORDER BY p.dateCreated DESC"),
#NamedQuery(name = "Post.selectPostsByTags", query = "SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags IN :tags") })
public class Post implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idpost;
#Lob
private String content;
private String title;
// bi-directional many-to-one association to User
#ManyToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "iduser")
private User user;
// bi-directional many-to-many association to Tag
#ManyToMany(cascade = CascadeType.PERSIST)
#JoinTable(name = "post_tag", joinColumns = #JoinColumn(name = "idpost"), inverseJoinColumns = #JoinColumn(name = "idtag"))
private List<Tag> tags = new ArrayList<Tag>();
#Temporal(TemporalType.DATE)
private Date date = null;
#Temporal(TemporalType.TIMESTAMP)
private Date dateCreated = new Date();
public Post() {
}
public int getIdpost() {
return this.idpost;
}
public void setIdpost(int idpost) {
this.idpost = idpost;
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public List<Tag> getTags() {
return this.tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
#Override
public String toString() {
return "Post [idpost=" + idpost + ", content=" + content + ", title="
+ title + ", date=" + date + "]";
}
}
This is Tag Entity
#Entity
#NamedQueries({
#NamedQuery(name = "Tag.selectTags", query = "SELECT tag FROM Tag tag WHERE tag.tagName LIKE :keyword"),
#NamedQuery(name = "Tag.selectMatchingTags", query = "SELECT t.tagName FROM Tag t WHERE t.tagName LIKE :keyword"),
#NamedQuery(name = "Tag.selectTagByName", query = "SELECT tag FROM Tag tag WHERE tag.tagName = :tagName"),
#NamedQuery(name = "Tag.selectTagsForAllPosts", query = "SELECT DISTINCT tag FROM Tag tag, Post post JOIN tag.posts posts WHERE post.user = :user")})
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idtag;
private String tagName;
// bi-directional many-to-many association to Post
#ManyToMany(mappedBy = "tags", cascade = CascadeType.PERSIST)
private List<Post> posts;
public Tag() {
}
public Tag(String tagName) {
this.tagName = tagName;
}
public int getIdtag() {
return this.idtag;
}
public void setIdtag(int idtag) {
this.idtag = idtag;
}
public String getTagName() {
return this.tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public List<Post> getPosts() {
return this.posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
#Override
public String toString() {
return tagName;
}
}
Try:
...
#NamedQuery(name = "Post.selectPostsByTags", query =
"SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE tags IN (:tags)") })
public class Post implements Serializable {
...
Use it like this:
#PersistenceContext
public EntityManager em;
...
List<Tag> ltags = new ArrayList<Tag>();
ltags.add(tagOne);
ltags.add(tagTwo);
List<?> list = em.createNamedQuery("Post.selectPostsByTags")
.setParameter("tags", ltags)
.getResultList();
for (Object object : list) {
System.out.println("Results: "+object);
}