I'm new to using JPQL/JPA and I somehow can't get this working:
public List<Bil> hentBiler(int kontor) {
List<Bil> biler = new ArrayList<Bil>();
TypedQuery<Bil> query = em.createQuery("SELECT o FROM Bil o WHERE o.kontornr = ?1", Bil.class);
query.setParameter(1, kontor);
}
The kontornr column in the database is an integer.
The error i recieve is this:
Exception Description: Problem compiling [SELECT o FROM Bil o WHERE o.kontornr = ?1].
[26, 36] The state field path 'o.kontornr' cannot be resolved to a valid type.
#Entity
public class Bil {
#Id
private String regNr;
private String merke;
private String modell;
private String farge;
private char gruppe;
private boolean ledig;
private int kontorNr;
The field is declared as
private int kontorNr;
The query is
SELECT o FROM Bil o WHERE o.kontornr = ?1
Java is case sensitive. kontronr != kontorNr.
Related
How write JPQL query with COUNT and GROUP BY and get result as Map<Integer,Integer>?
public class CommentEntity {
private int id;
private int parentId;
private EntityParentType parentType;
private Long replyCounts;
private String author;
private String comment;
}
.
public enum EntityParentType {
PERSON,
EVENT,
COMMENT;
}
I wrote MySQL query and this work fine:
SELECT parent_id, COUNT(*) FROM comment AS c WHERE c.parent_type = 2 AND c.parent_id IN (64,65) GROUP BY parent_id
but JPQL query is fail:
#Repository
#Transactional(readOnly = true)
public interface CommentRepository extends JpaRepository<CommentEntity, Integer> {
#Query(value = "SELECT c.parentId, COUNT(c.id) FROM CommentEntity AS c WHERE c.parentType = ?1 AND c.parentId IN (?2) GROUP BY c.parentId")
Map<Integer, Integer> findReplyCountByParentIds(EntityParentType entityParentType, List<Integer> ids);
}
.
Method threw 'org.springframework.dao.IncorrectResultSizeDataAccessException' exception.
result returns more than one elements
below is fail too:
#Query(value = "SELECT c.parentId, COUNT (c.id) FROM CommentEntity AS c WHERE c.parentType = ?1 AND c.parentId IN (?2) GROUP BY c.parentId")
List<Map<Integer, Integer>> findReplyCountByParentIds(EntityParentType entityParentType, List<Integer> ids);
.
Method threw 'org.springframework.dao.InvalidDataAccessApiUsageException' exception.
No aliases found in result tuple! Make sure your query defines aliases!
I tried add pacakge to CommentEntity and also is fail
One workaround is to use the constructor syntax as follows:
SELECT NEW org.apache.commons.lang3.tuple.ImmutablePair(c.parentId, COUNT(c.id)) FROM ...
Of course, you could use any other class in place of ImmutablePair (e.g. a concrete implementation of Map.MapEntry). You then declare the result as a List<ImmutablePair> and collect the results into a map in your service method.
I have two entity:
public class public class Person implements Serializable {
private static final long serialVersionUID = -8729624892493146858L;
#Column(name="name")
private String name;
...
#JoinColumn(name = "idcity",referencedColumnName = "id",nullable = true)
#ManyToOne(targetEntity = City.class, fetch = FetchType.EAGER)
private City city
...
}
and the related entity (extract):
public class City{
Long id;
String name;
...
}
Now i'm creating a criteria query in a standard way, querying the Person class:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(selectClass);
Root<T> root = query.from(this.entityClass);
Selection selezioni[] = new Selection[selections.length];
for(int i=0; i< selections.length; i++){
selezioni[i] = CriteriaHelper.getField(selections[i], cb, root);
}
query.select(cb.construct(selectClass, selezioni));
where entityClass is Person and selection and selectClass are used to compile the SELECT clause. In the select i've person.city.name field.
This system create a query with where clause:
select person.name, ..., city.name from person, city WHERE person.idcity = city.id...
but city is not required, so the records without city are not fetched.
Without changing all my automatic system, does exists a simpler way to force the use on LEFT JOIN for the relationship than adding a system to create root.join("field",LEFT)?
Note: the method CriteriaHelper.getField() return a Path starting from the root object
I have namedQuery in Entity class defined as
#NamedQuery(name = "Emp.findAll",
query = " select new test.entity.Emp(o.empNo, o.salary, o.project) from Emp o ")
Constructor
public Emp(String empNo, String salary, Project project) {
this.empNo = empNo;
this.salary= salary;
this.project = project;
}
and generated SQL is
SELECT t0.emp_no, t0.salary, t1.project_id, t1.project_name, t1.project_desc
FROM EMP t0, PROJECTS t1 WHERE (t1.project_id (+) = t0.project_id)
In namedQuery how do I selectively declare projectId and projectName instead of all attributes from Project class? I wouldn't like to display all attributes of Project class in namedQuery.
How can I achieve this?
Update 1
public Emp(String empNo, String salary, Long projectId, String projectName) {
Project pr = new Project();
this.empNo = empNo;
this.salary= salary;
pr.setProjectId = projectId;
pr.setProjectName = projectName;
}
Try this (and update the constructor accordingly)
#NamedQuery(name = "Emp.findAll",
query = " select new test.entity.Emp(o.empNo, o.salary, p.projectId, p.projectName) from Emp o inner join o.project p ")
Constructor will be something like this
public Emp(String empNo, String salary, Long projectId, String projectName) {
this.empNo = empNo;
this.salary= salary;
Project pr = new Project();
pr.setProjectId(projectId);
pr.setProjectName(projectName);
this.project = pr;
}
I have the following JPQL query:
List<DestinationInfo> destinations = em.createQuery("SELECT NEW com.realdolmen.patuva.dto.DestinationInfo(d.name, d.continent, MIN(t.departureDate), MIN(t.pricePerDay), COUNT(t.id))" +
" FROM Destination d, Trip t" +
" WHERE d.continent = :continent " +
" GROUP BY d.name, d.continent").setParameter("continent", searchedContinent).getResultList();
If I run this I get the error:
javax.ejb.EJBTransactionRolledbackException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.realdolmen.patuva.dto.DestinationsList]
If I leave out the COUNT(t.id) and remove that parameter from my DestinationInfo constructor it works fine. Why can't I map the COUNT(t.id) to my DestinationInfo DTO.
This is my DestinationInfo class:
public class DestinationInfo {
private String name;
private Continent continent;
private Date earliestDeparture;
private Integer totalNumTrips;
private BigDecimal lowestPrice;
public DestinationInfo(String name, Continent continent, Date earliestDeparture, BigDecimal lowestPrice, Integer totalNumTrips) {
this.name = name;
this.continent = continent;
this.earliestDeparture = earliestDeparture;
this.totalNumTrips = totalNumTrips;
this.lowestPrice = lowestPrice;
}
// getters and setters
}
Apparently COUNT(t.id) returns a number of type long. Changing the DestinationInfo class to the following makes it work:
public class DestinationInfo {
private String name;
private Continent continent;
private Date earliestDeparture;
private long totalNumTrips;
private BigDecimal lowestPrice;
public DestinationInfo(String name, Continent continent, Date earliestDeparture, BigDecimal lowestPrice, long totalNumTrips) {
this.name = name;
this.continent = continent;
this.earliestDeparture = earliestDeparture;
this.totalNumTrips = totalNumTrips;
this.lowestPrice = lowestPrice;
}
// getters and setters
}
I am using EL and i keep getting 0 when i run the query below. I want to get the count of applicants (AP) that are currently active. The child entity Applicant is of Person and i want to avoid querying all elements of Person?
#RooJavaBean
#RooToString
#RooEntity(identifierColumn = "personID", inheritanceType = "SINGLE_TABLE")
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING, length = 20)
#DiscriminatorValue("P")
public class Person {
#NotNull
#Size(min = 1, max = 50)
private String FirstName;
#NotNull
#Size(min = 1, max = 50)
private String LastName;
}
The child entity 'Applicant'
#RooJavaBean
#RooToString
#RooEntity
#DiscriminatorValue("AP")
public class Applicant extends Person{
private String major;
private String nativeLanguage;
private String ethnicity;
private String hispanic;
}
My query attempt:
/**
*
* #return
*/
public int getCountActiveApplicants(){
EntityManager entityManager = factory.createEntityManager();
int value = entityManager.createQuery("select count(distinct o) from Person o where o.TYPE = \"AP\" AND o.active = \"Yes\" ").getFirstResult();
System.out.println("wowzer " + value + "\n");
return value;
}
Why don't you simply count the applicants?
select count(distinct a) from Applicant a where a.active = true
EclipseLink will transform this in SQL and add the where clause on the discriminator for you.
Remember that JPQL works with your entities and their persistent fields/properties. It knows about their association and their inheritance hierarchy. JPQL never uses table and column names.
(Side note: why use "Yes" for a boolean field?)