How to filter by faculty name? - jpa

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);
}

Related

Spring Boot and JpaRepository sort by distance with latitude and longitude params

I have a problem creating a query using the JpaRepository interface. I use the Pageable mechanism. How can I add sort by distance? Geographic parameters available at Event Place. (Latitude, longitude). I would like to add also the ability to limit distance by range. E.g:
"Where distance <: range".
I would like the distance to be returned in the "distance" field, which is #Transient.
EventRepository
#Repository
public interface EventRepository extends JpaRepository<Event, Long> {
public static final String GET_PAGE_QUERY = "WHERE " +
"(:searchTerm is null or e.title like '%:searchTerm%') AND " +
"((:userListId) is null or e.user.id in (:userListId)) AND " +
"((:sportTypeIdList) is null or e.sportType.id in (:sportTypeIdList)) " ;
#Query(value = "SELECT e FROM Event e " + GET_PAGE_QUERY,
countQuery = "SELECT COUNT(e) FROM Event e " + GET_PAGE_QUERY)
Page<Event> getPage(#Param("searchTerm") String searchTerm, #Param("userListId") List<Long> userListId, #Param("sportTypeIdList") List<Long> sportTypeIdList, Pageable pageable);
}
Event
#Getter
#Setter
#Entity
#Table(name = "event")
public class Event {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "event_seq")
#SequenceGenerator(name = "event_seq", sequenceName = "event_seq", allocationSize = 1)
private Long id;
#Column(name = "TITLE", length = 50, nullable = false)
#NotNull
#Size(min = 4, max = 50)
private String title;
#Column(name = "DESCRIPTION", length = 500, nullable = false)
#NotNull
#Size(min = 4, max = 500)
private String description;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
private SportType sportType;
#OneToOne(fetch = FetchType.EAGER, optional = false)
private EventPlace place;
#ManyToOne(optional = false)
private User user;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
#Column(name = "CREATE_DATE", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date createDate = new Date();
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
#Column(name = "START_DATE", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date startDate;
#Column(name = "STATUS", nullable = false)
#NotNull
#Enumerated(EnumType.STRING)
private EventStatus status = EventStatus.ACTIVE;
#Transient
private double distance;
}
EventPlace
#Getter
#Setter
#Entity
public class EventPlace {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "event_place_seq")
#SequenceGenerator(name = "event_place_seq", sequenceName = "event_place_seq", allocationSize = 1)
private Long id;
#Column(name = "NAME", length = 50, nullable = false)
#NotNull
#Size(min = 4, max = 50)
private String name;
#Column(name = "CITY", length = 50, nullable = false)
#NotNull
#Size(min = 4, max = 50)
private String city;
#Column(name = "STREET", length = 50, nullable = false)
#NotNull
#Size(min = 4, max = 50)
private String street;
#Column(name = "ZIP_CODE", length = 50, nullable = false)
#NotNull
#Size(min = 4, max = 50)
private String zipCode;
#Column(name = "DESCRIPTION", length = 500, nullable = false)
#NotNull
#Size(min = 4, max = 500)
private String description;
#Column(name = "LATITUDE", nullable = false)
#NotNull
private Double latitude;
#Column(name = "LONGITUDE", nullable = false)
#NotNull
private Double longitude;
}

JPA WHERE clause

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")

Bean validation succeeded but failed on jpa merge method

I want to persist an entity(MyEntity) with merge method. This entity have some beans validation.
public class MyEntity extends AbstractEntity {
#Basic(optional = false)
#Column(name = "city", length = 255, nullable = false)
#NotNull
#NotEmpty(message = "{myentity.validation.size.name}")
private String city;
private String number;
#Basic(optional = false)
#Column(name = "zipcode", length = 255, nullable = false)
#NotNull
private String zipcode;
private String phoneNumber;
#Email(message = "{myentity.validation.conform.email}")
#Size(min = 2, max = 100, message = "{myentity.validation.size.email}")
private String email;
private String website;
private String gpsLocation;
#ElementCollection()
#CollectionTable(name = "translation_poi", joinColumns = #JoinColumn(name = "point_id"))
#MapKeyJoinColumn(name = "locale")
#NotEmpty
private Map<Locale, MyEntityI18n> translations = new HashMap<>();
}
#Embeddable
public class MyEntityI18n implements java.io.Serializable {
#Basic(optional = false)
#Column(name = "name", length = 255, nullable = false)
#NotNull
#NotEmpty(message = "{myentity.validation.size.name}")
private String name;
#Column(name = "comment", length = 1200)
private String comment;
#Column(name = "short_description", length = 1200)
private String shortDescription;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The merge succeeded on an existing entity value but with a new entity the merge failed despite the fact that the following validation succeeded.
private boolean validate(MyEntity poi) {
boolean result = true;
Set<ConstraintViolation<MyEntity>> constraintViolations = validator.validate(poi);
if (constraintViolations.size() > 0) {
result = false;
for (ConstraintViolation<MyEntity> constraints : constraintViolations) {
FacesContext context = FacesContext.getCurrentInstance();
String message = constraints.getPropertyPath() + " " + constraints.getMessage();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, constraints.getMessage(), message));
}
}
return result;
}
Try to add a #Valid to MyEntity.translations property. I think that your validation method hasn't take account the MyEntityI18n.name validation.
About merge fails, Do you have a not-null DB constraint on the MyEntityI18n.name field?
Good luck!

Insert object with composite primary key

I need help with this. With code is more clear, this is my function to persist:
public String finalizarCompra() {
Pedido pedido = new Pedido();
pedido.setEstado("almacen");
pedido.setFechaVenta(new Date());
pedido.setIdUsuario(loginBean.getUsuario());
Producto p;
Integer i;
DetPedido detPedido;
List<DetPedido> lista = new ArrayList<>();
for (Map.Entry e : productos.entrySet()) {
detPedido = new DetPedido();
p = (Producto) e.getKey();
i = (Integer) e.getValue();
detPedido.setProducto(p);
detPedido.setCantidad(i);
detPedido.setPrecioUnidad(p.getPrecioUnidad());
detPedido.setPedido(pedido);
lista.add(detPedido);
detPedidoBean.insert(detPedido);
}
pedido.setDetPedidoCollection(lista);
pedidoBean.insert(pedido);
return "";
}
This is my Pedido Entity:
#Entity
public class Pedido implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ID_PEDIDO")
private Integer idPedido;
#Basic(optional = false)
#NotNull
#Column(name = "FECHA_VENTA")
#Temporal(TemporalType.TIMESTAMP)
private Date fechaVenta;
#Column(name = "FECHA_ENVIO")
#Temporal(TemporalType.TIMESTAMP)
private Date fechaEnvio;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(name = "ESTADO")
private String estado;
#JoinColumn(name = "ID_USUARIO", referencedColumnName = "ID_USUARIO")
#ManyToOne(optional = false)
private Usuario idUsuario;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "pedido")
private Collection<DetPedido> detPedidoCollection;
// Getters and Setters //
This is my DetPedido Entity:
#Entity
public class DetPedido implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected DetPedidoPK detPedidoPK;
#Basic(optional = false)
#NotNull
#Column(name = "CANTIDAD")
private Integer cantidad;
#Basic(optional = false)
#NotNull
#Column(name = "PRECIO_UNIDAD")
private Double precioUnidad;
#JoinColumn(name = "ID_PRODUCTO", referencedColumnName = "ID_PRODUCTO", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Producto producto;
#JoinColumn(name = "ID_PEDIDO", referencedColumnName = "ID_PEDIDO", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Pedido pedido;
// Getters and Setters //
And this is my DetPedidoPK:
#Embeddable
public class DetPedidoPK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "ID_PEDIDO")
private Integer idPedido;
#Basic(optional = false)
#NotNull
#Column(name = "ID_PRODUCTO")
private Integer idProducto;
// Getters and Setters //
The Entities ara generated automatically from the Database, also DetPedidoPK, and now I don't know how to save a Pedido. I tried with the code above, but it doesn't work.
Can anybody help me?
Greetings.
If you are using JPA 1.0 and this entity model, then you will need to persist and flush both Producto and Pedido instances to have their IDs assigned before you can persist the DetPedido instance that will reference them. Once that is done, you will need to manually set the id values in DetPedido's DetPedidoPK instance so that they match the referenced Producto and DetPedido key values. You cannot insert DetPedido without the DetPedidoPK values having been set.
JPA 2.0 supports derived IDs, which allows marking the relationship as either #ID or #MapsId, indicating that the ID values should be pulled from the joincolumn associated to the relationship. In this case, it would become:
#ManyToOne(optional = false)
#MapsId("idProducto")
private Producto producto;
#ManyToOne(optional = false)
#MapsId("idPedido")
private Pedido pedido;
If you wanted, you could do away with the embeddable within DetPedido and just mark the relationships as the #Id, and because it is composite you would use the DetPedidoPK as the PK 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