JPA WHERE clause - jpa

I am asking about WHERE clause. I have searched internet but I didn`t find answer for my question.
I have a few entity classes, which i represent below:
#NamedQuery(name = "selectTrasy",
query = "SELECT t FROM Trasa t WHERE t.raport = :raport ORDER BY t.id")
#Entity
public class Trasa implements Serializable {
#Id
#Column(name = "id", unique = true )
#GeneratedValue
private Long id;
#Column(name = "data_z")
private Date dataz;
#Column(name = "data_do")
private Date datado;
#Column(name = "czas_z")
private String czasZ;
#Column(name = "czas_do")
private String czasDo;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "miejscowosc_z")
private MiejscowoscDB miejscowoscZ;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "miejscowosc_do")
private MiejscowoscDB miejscowoscDo;
#OneToOne(fetch = FetchType.LAZY)
private Uzytkownik user;
#OneToOne(fetch = FetchType.LAZY)
private Raport raport;
#Override
public boolean equals(Object other) {
return (other != null && getClass() == other.getClass() && id != null)
? id.equals(((Trasa) other).id)
: (other == this);
}
#Override
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}
//next I have getters and setters
}
#Entity
public class Raport implements Serializable {
#Id
#Column(name = "id", unique = true )
#GeneratedValue
private Long id;
#Column(name = "data")
private Date data;
#Column(name = "nazwa")
private String nazwa;
#Enumerated(EnumType.STRING)
private Powod powod;
#OneToOne(fetch = FetchType.LAZY)
private Uzytkownik uzytkownik;
#Override
public boolean equals(Object other) {
return (other != null && getClass() == other.getClass() && id != null)
? id.equals(((Raport) other).id)
: (other == this);
}
#Override
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}
//getters and setters
}
My question is why this query doesn`t work properly. Returned list is empty, but recordes exists in database, when I want return all Trasa records there is everything ok, only not works when I add WHERE clause with raport property.
trasy = (List<Trasa>)(manager.createNamedQuery("selectTrasy")
.setParameter("raport", propertyWydatek.getRaport())
.getResultList());

Change your query to:
#NamedQuery(name = "selectTrasy",
query = "SELECT t FROM Trasa t WHERE t.raport.id = :raportId ORDER BY t.id")
and run it like this:
trasy = (List<Trasa>)(manager.createNamedQuery("selectTrasy")
.setParameter("raportId", propertyWydatek.getRaport().getId())
.getResultList());
Other version of the query:
#NamedQuery(name = "selectTrasy",
query = "SELECT t FROM Trasa t join t.raport r WHERE r.id = :raportId ORDER BY t.id")

Related

Rest API order by name

I'm trying to create my own REST API and I'm having trouble trying to order my data by name. currently, I am able to display all the data from the styles table, however, I wish to sort them alphabetically.
I was able to do a filter by extracting the year from the date and checking if that was in the database, this is shown in
public List<Beers> getAllBeersByYear(int year) {
EntityManager em = DBUtil.getEMF().createEntityManager();
List<Beers> list = null;
List<Beers> beersToRemove = new ArrayList<>();
try {
list = em.createNamedQuery("Beers.findAll", Beers.class)
.getResultList();
if (list == null || list.isEmpty()) {
list = null;
}
} finally {
em.close();
}
Calendar cal = Calendar.getInstance();
for (Beers beer : list) {
cal.setTime(beer.getLastMod());
if (cal.get(Calendar.YEAR) != year) {
beersToRemove.add(beer);
}
}
list.removeAll(beersToRemove);
return list;
}
the controller is
#GetMapping(produces=MediaType.APPLICATION_JSON_VALUE)
public List<Styles> GetAllStyles() {
return service.getAllStyles();
}
would it be possible to do something similar to the service and controller where instead of filtering the data, it can sort by the name of a column
the service is
public List<Styles> getAllStyles() {
EntityManager em = DBUtil.getEMF().createEntityManager();
List<Styles> list = null;
try {
list = em.createNamedQuery("Styles.findAll", Styles.class)
.getResultList();
if (list == null || list.isEmpty()) {
list = null;
}
} finally {
em.close();
}
return list;
}
the JPA I am using is
#Entity
#Table(name = "styles")
#NamedQueries({
#NamedQuery(name = "Styles.findAll", query = "SELECT s FROM Styles s"),
#NamedQuery(name = "Styles.findById", query = "SELECT s FROM Styles s WHERE s.id = :id"),
#NamedQuery(name = "Styles.findByCatId", query = "SELECT s FROM Styles s WHERE s.catId = :catId"),
#NamedQuery(name = "Styles.findByStyleName", query = "SELECT s FROM Styles s WHERE s.styleName = :styleName"),
#NamedQuery(name = "Styles.findByLastMod", query = "SELECT s FROM Styles s WHERE s.lastMod = :lastMod")})
public class Styles 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
#Column(name = "cat_id")
private int catId;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "style_name")
private String styleName;
#Basic(optional = false)
#NotNull
#Column(name = "last_mod")
#Temporal(TemporalType.TIMESTAMP)
private Date lastMod;
public Styles() {
}
public Styles(Integer id) {
this.id = id;
}
public Styles(Integer id, int catId, String styleName, Date lastMod) {
this.id = id;
this.catId = catId;
this.styleName = styleName;
this.lastMod = lastMod;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getCatId() {
return catId;
}
public void setCatId(int catId) {
this.catId = catId;
}
public String getStyleName() {
return styleName;
}
public void setStyleName(String styleName) {
this.styleName = styleName;
}
public Date getLastMod() {
return lastMod;
}
public void setLastMod(Date lastMod) {
this.lastMod = lastMod;
}
#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 Styles)) {
return false;
}
Styles other = (Styles) 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 "Service.Styles[ id=" + id + " ]";
}
}
You can use #OrderBy annotation
https://www.logicbig.com/tutorials/java-ee-tutorial/jpa/order-by-annotation.html
Just create another query:
#NamedQuery(name = "Styles.findAll", query = "SELECT s FROM Styles s ORDER BY s.name")
And why are you filtering in the code when you can add a query with a where condition?

How to filter by faculty name?

I want to implement lazy record loading on a Primefaces DataTable (version 7). I have two entities, one is called Faculties and the other is Careers, which are related. The datatable correctly shows the list of all the races (includes pagination and filtering), the problem I have is that I do not know how to filter the races by the name of a certain faculty, since I do not know how to include the join in the query that I leave then.
Could you guide me on how to solve it please?
Entity Faculties
public class Facultades implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idfacultad")
private Integer idfacultad;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(name = "nombre")
private String nombre;
#Size(max = 20)
#Column(name = "abreviatura")
private String abreviatura;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idfacultad")
private List<Carreras> carrerasList;}
Entity Carreras
public class Carreras implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idcarrera")
private Integer idcarrera;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 150)
#Column(name = "nombre")
private String nombre;
#Basic(optional = false)
#NotNull
#Column(name = "tipo")
private int tipo;
#JoinColumn(name = "idfacultad", referencedColumnName = "idfacultad")
#ManyToOne(optional = false)
private Facultades idfacultad;}
Query findByParams
public List<Carreras> findByParams(int start, int size, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Carreras> criteriaQuery = criteriaBuilder.createQuery(Carreras.class);
Root<Carreras> root = criteriaQuery.from(Carreras.class);
CriteriaQuery<Carreras> select = criteriaQuery.select(root);
Join<Carreras, Facultades> facultad = root.join("idfacultad");
if (sortField != null) {
criteriaQuery.orderBy(sortOrder == SortOrder.DESCENDING ? criteriaBuilder.asc(root.get(sortField)) : criteriaBuilder.desc(root.get(sortField)));
}
if (filters != null && filters.size() > 0) {
List<Predicate> predicados = new ArrayList<>();
filters.entrySet().forEach((entry) -> {
String key = entry.getKey();
Object val = entry.getValue();
if (!(val == null)) {
// Construimos la expresion con los predicados que si existan
Expression<String> expresion = root.get(key).as(String.class);
Predicate predicado = criteriaBuilder.like(criteriaBuilder.lower(expresion), "%" + val.toString().toLowerCase() + "%");
predicados.add(predicado);
}
});
if (predicados.size() > 0) {
criteriaQuery.where(criteriaBuilder.and(predicados.toArray(new Predicate[predicados.size()])));
}
}
// Creamos la consulta
TypedQuery<Carreras> consulta = em.createQuery(select);
consulta.setFirstResult(start);
consulta.setMaxResults(size);
return consulta.getResultList();
}
You need to manually check if the filter key equals the Facultades object, and in that case create a predicate on the joined expression that you have already created:
if (key.equals("Facultad")) {
expresion = facultad.get("nombre").as(String.class);
} else {
expresion = root.get(key).as(String.class);
}

JPA merge does insert new entity instead of update existing one

It seems like that when I update my existing entity using jpa merge, it does insert entity with same id instead of updating existing one expected. Because after insertion, database row order lost. But I still have same entities with same ids, does Jpa use insertion to update? I mean does it delete existing entity and insert again with updated value to do its update job. Main chaos is database order is lost then.
Here is my listener method: userService Is EJB class within I use JPA.
public void onEditUserOrganization(RowEditEvent event){
UserOrganization uorg =(UserOrganization) event.getObject();
try {
userService.updateUserOrganization(uorg);
} catch (UserException ex) {
ex.printStackTrace();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("error)"));
}finally{
parentlist = getUserOrganizationParents();
branchlist = getUserOrganizationBranches();
}
}
Here is my main update method
#Override
public void updateUserOrganization(UserOrganization org) throws UserException{
if(org != null && !em.contains(org)){
try{
UserOrganization existing = em.find(UserOrganization.class, org.getUorgId());
existing.setOrgcode(org.getOrgcode());
existing.setOrgname(org.getOrgname());
existing.setParent(org.getParent());
}catch(Exception e){
throw new UserException("Couldn't update user org with id " + org.getUorgId());
}
}
}
Here is my entity class:
public class UserOrganization implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "uorg_id", nullable = false)
private Integer uorgId;
#Basic(optional = false)
#NotNull
#Column(name = "parent", nullable = false)
private short parent;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 10)
#Column(name = "orgcode", nullable = false, length = 10)
private String orgcode;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 150)
#Column(name = "orgname", nullable = false, length = 150)
private String orgname;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "uorgId")
private List<refMain> refList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "uorgId")
private List<User1> user1List;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userOrganization")
private List<Bankrelation> relationList;
public UserOrganization() {
}
//getter setters..
#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 UserOrganization)) {
return false;
}
UserOrganization other = (UserOrganization) object;
if ((this.uorgId == null && other.uorgId != null) || (this.uorgId != null && !this.uorgId.equals(other.uorgId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "mn.bs.crasmon.model.UserOrganization[ uorgId=" + uorgId + " ]";
}
What is the best way to do update In JPA

ORA-01400: cannot insert NULL in #manytomany unidierctional

I am inserting a User object with roles(existing) roles .
It is giving me unable insert null in user_role.id
Schema:
#Entity
#Table(name = "user_data")
public class User extends Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
/**
* user can have set of roles profiles
*/
#ManyToMany(cascade = {CascadeType.ALL} ,fetch=FetchType.EAGER)
#JoinTable(name = "user_role", joinColumns = { #JoinColumn(name = "user_id", referencedColumnName = "id") }, inverseJoinColumns = { #JoinColumn(name = "role_id", referencedColumnName = "id") })
private Set<Role> roles;
}
#Entity #Table(name = "role")
public class Role extends Serializable {
private static final long serialVersionUID = -5954247513572163065L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#ManyToMany
#JoinTable(name = "role_permission", joinColumns = { #JoinColumn(name = "role_id",
referencedColumnName = "id") },
inverseJoinColumns = { #JoinColumn(name = "permission_id",
referencedColumnName = "id") })
private Set<Permission> permissions;
[...]
}
Now when i am trying to create user it is giving me the exception
java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("USER_ROLE"."ID")
For creating a user I am using spring repository code as below:
#Override
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public User createUser(User user) throws BusinessException {
List<Error> errors = new ArrayList<Error>();
validateUserRoles(user ,errors);
if ( errors.size() > 0 )
{
throw new BusinessException(errors);
}
user.setUserIdentifier(user.getUserIdentifier().trim());
logger.info("Creating User with username: " + user.getUserIdentifier());
return this.userRepositotry.save(user);
}
private void validateUserRoles(User user ,List<Error> errors) {
Set<Role> roles = new HashSet<Role>();
if (user.getRoles() != null)
{
for(Role role : user.getRoles())
{
Role r = null;
if(role.getId() != null)
{
r = this.roleRepository.findOne(role.getId());
} else if( role.getName() != null )
{
r = this.roleRepository.findByName(role.getName());
}
if(r == null)
{
errors.add(new Error(ErrorCode.INVALID_ARGUMENTS,"Invalid user Role.",r));
} else
{
roles.add(r);
}
}
}
user.setRoles(roles);
}
Your user_role join table has an id column, that Hibernate doesn't know about. All hibernate knows about is the role_id and user_id columns. The id column isn't useful, and you should remove it from the user_role table. If you leave it there, you need to make it nullable, or to make it have a default value.

Why JPA doesnt generate a join junction table in this case

I have two tables Students and Books , with a many to many relationship. The code of both are given below. Now when I try to run the code I get the error.
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'acme.book_stud' doesn't exist
Error Code: 1146
Call: INSERT INTO book_stud (idStudents, idBooks) VALUES (?, ?)
bind => [2 parameters bound]
It seems like JPA is trying to write to a juction table which does not exist (in this case it assumes a junction table books_students is already created so it doesnt create one.). It works if I create a books_students but I dont want to do that since its JPA responsibility to create it. Is there a way in which I could explicitly tell it to create one. ? (I am taking a wild guess here - but I guess when creating a persitance unit I specified "none" I think thats why it didnt create that table . Am I correct ? Anyways here are my Student and Books Classes
BOOKS CLASS
#Entity
#Table(name = "books")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Books.findAll", query = "SELECT b FROM Books b"),
#NamedQuery(name = "Books.findByIdBooks", query = "SELECT b FROM Books b WHERE b.idBooks = :idBooks"),
#NamedQuery(name = "Books.findByBookName", query = "SELECT b FROM Books b WHERE b.bookName = :bookName"),
#NamedQuery(name = "Books.findByBookType", query = "SELECT b FROM Books b WHERE b.bookType = :bookType")})
public class Books implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "idBooks")
private String idBooks;
#Size(max = 45)
#Column(name = "BookName")
private String bookName;
#Size(max = 45)
#Column(name = "BookType")
private String bookType;
/******************************************ADDED **********************/
#ManyToMany
#JoinTable(name = "book_stud",
joinColumns = { #JoinColumn(name = "idStudents") },
inverseJoinColumns = { #JoinColumn(name = "idBooks") })
/**************************************ENDED*****************************/
public Books() {
}
public Books(String idBooks) {
this.idBooks = idBooks;
}
public String getIdBooks() {
return idBooks;
}
public void setIdBooks(String idBooks) {
this.idBooks = idBooks;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookType() {
return bookType;
}
public void setBookType(String bookType) {
this.bookType = bookType;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idBooks != null ? idBooks.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 Books)) {
return false;
}
Books other = (Books) object;
if ((this.idBooks == null && other.idBooks != null) || (this.idBooks != null && !this.idBooks.equals(other.idBooks))) {
return false;
}
return true;
}
#Override
public String toString() {
return "domain.Books[ idBooks=" + idBooks + " ]";
}
}
STUDENT CLASS
#Entity
#Table(name = "students")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "StudentEnroll.findAll", query = "SELECT s FROM StudentEnroll s"),
#NamedQuery(name = "StudentEnroll.findByIdStudents", query = "SELECT s FROM StudentEnroll s WHERE s.idStudents = :idStudents"),
#NamedQuery(name = "StudentEnroll.findByName", query = "SELECT s FROM StudentEnroll s WHERE s.name = :name"),
#NamedQuery(name = "StudentEnroll.findByRoll", query = "SELECT s FROM StudentEnroll s WHERE s.roll = :roll"),
#NamedQuery(name = "StudentEnroll.findBySsn", query = "SELECT s FROM StudentEnroll s WHERE s.ssn = :ssn"),
#NamedQuery(name = "StudentEnroll.findByProgram", query = "SELECT s FROM StudentEnroll s WHERE s.program = :program")})
public class StudentEnroll implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 40)
#Column(name = "idStudents")
private String idStudents;
#Size(max = 45)
#Column(name = "Name")
private String name;
#Column(name = "Roll")
private Integer roll;
#Column(name = "SSN")
private Integer ssn;
#Size(max = 45)
#Column(name = "Program")
private String program;
#JoinColumn(name = "CustomerID", referencedColumnName = "UserID")
#ManyToOne
private Customer customerID;
//#OneToMany(mappedBy = "studentRoll")
#OneToMany(mappedBy = "studentRoll",cascade = CascadeType.REMOVE)//added REMOVE
private Collection<Subject> subjectCollection;
/**************************ADDED*****************************/
#ManyToMany
#JoinTable(name = "book_stud",
joinColumns = { #JoinColumn(name = "idBooks") },
inverseJoinColumns = { #JoinColumn(name = "idStudents") })
/**********************************END**********************/
public StudentEnroll() {
}
public StudentEnroll(String idStudents) {
this.idStudents = idStudents;
}
public String getIdStudents() {
return idStudents;
}
public void setIdStudents(String idStudents) {
this.idStudents = idStudents;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getRoll() {
return roll;
}
public void setRoll(Integer roll) {
this.roll = roll;
}
public Integer getSsn() {
return ssn;
}
public void setSsn(Integer ssn) {
this.ssn = ssn;
}
public String getProgram() {
return program;
}
public void setProgram(String program) {
this.program = program;
}
public Customer getCustomerID() {
return customerID;
}
public void setCustomerID(Customer customerID) {
this.customerID = customerID;
}
#XmlTransient
public Collection<Subject> getSubjectCollection() {
return subjectCollection;
}
public void setSubjectCollection(Collection<Subject> subjectCollection) {
this.subjectCollection = subjectCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idStudents != null ? idStudents.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 StudentEnroll)) {
return false;
}
StudentEnroll other = (StudentEnroll) object;
if ((this.idStudents == null && other.idStudents != null) || (this.idStudents != null && !this.idStudents.equals(other.idStudents))) {
return false;
}
return true;
}
#Override
public String toString() {
return "domain.StudentEnroll[ idStudents=" + idStudents + " ]";
}
}