I'm trying to build a request using Criteria with 2 sum but having this error:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
Stats
Stats class:
#Entity
#Table(name = "STATS")
#Getter
public class Stats{
#Id
#Column(name = "STAT_ID")
private int statId;
#Column(name = "NB_STATS_CONFIRMED")
private long nbStatsConfirmed;
#Column(name = "NB_STATS_DELETED")
private long nbStatsDeleted;
#Column(name = "DATE_STAT")
private Date dateStat;
}
Looks like:
STAT_ID NB_STATS_CONFIRMED NB_STATS_DELETED DATE_STAT
1 5 2 2018-01-23
2 2 1 2018-01-22
3 8 0 2018-01-20
I want to sum NB_STATS_CONFIRMED and NB_STATS_DELETED between 2 dates (DATE_STAT).
Criteria request:
#SuppressWarnings("unchecked")
#Override
public List<Stats> listStats(final Date start, final Date end) {
Criteria cr = createRequest(); // method creating a criteria
if (start != null) {
cr.add(Restrictions.ge("dateStat", start));
}
if (fin != null) {
cr.add(Restrictions.le("dateStat", end));
}
cr.setProjection(Projections.projectionList()
.add(Projections.sum("nbStatsConfirmed"), "nbStatsConfirmed")
.add(Projections.sum("nbStatsCanceled"), "nbStatsCanceled"));
return cr.list();
}
And then I call the method:
List<Stats> listStats = dao.listStats(start, end);
I tried [Ljava.lang.Object; cannot be cast to & Sum projection and results constraint
What am I doing wrong ?
I found a solution if some one is interested but have to do 2 requests:
long nbStatsConfirmed = (long) AJobUtil.valeurDefaut((cr.setProjection(
Projections.sum("nbStatsConfirmed"))
.uniqueResult()), (long) 0);
long nbStatsCanceled = (long) AJobUtil.valeurDefaut((cr.setProjection(
Projections.sum("nbStatsCanceled"))
.uniqueResult()), (long) 0);
long[] stats = { nbStatsConfirmed, nbStatsCanceled };
return stats;
Still open if you have a different solution (with 1 request) !
Related
I would like to run a native Query through the entity manager with spring boot framework, which will return the EXERCICIO, FONTE, FONTEDET, NOMEFONTE, ATUAL, SALDO properties, but I'm getting this error:
ERROR: org.springframework.orm.jpa.JpaSystemException: Could not resolve PropertyAccess for EXERCICIO
NOTE: I've tried a lots of solutions from StackOverflow and other websites, but none of them worked well. This SQL query is working fine when I execute in the Oracle SQL developer and return all properties mentionated above.
#Override
public List<ReturnSqlResult> read(Integer ano, Integer mesInicial, Integer mesFinal) {
String sql = "select
s.exercicio as exercicio,
o.orgao as orgao,
fr.fonte as fonte,
fr.fonte_detalhe as fonte_det,
fr.nome as nome_fonte,
sum(
case when s.mes_lancamento = :mesInicial then
s.vl_saldo_inicial
else 0
end + case
when p.natureza_conta = 'D' then
s.vl_mensal_debito - s.vl_mensal_credito
else s.vl_mensal_credito - s.vl_mensal_debito
end
) as atual from secretarias sec,
orgaos_sicom o,
saldos_mensais_secretaria s
left join fontes_recursos fr on fr.exercicio =
s.exercicio
and fr.gestao = s.gestao
and lpad(to_char(fr.fonte), 3, '0') =
substr(s.cc_tradutor, 1, 3)
and lpad(to_char(fr.fonte_detalhe), 4, '0') =
substr(s.cc_tradutor, 4, 4),
eventos_contas ec,
plano_contas pwhere sec.exercicio in (
:ano,
:ano - 1
and o.orgao = sec.orgao
and s.exercicio = sec.exercicio
and s.gestao = o.gestao
and s.mes_lancamento <> 13
and s.mes_lancamento >= :mesInicial
and s.mes_lancamento <= :mesFinal
and ec.exercicio = s.exercicio
and ec.gestao = s.gestao
and ec.evento = 9922
and ec.conta_contabil = s.conta_contabil
and p.exercicio = ec.exercicio
and p.gestao = ec.gestao
and p.conta_contabil = ec.conta_contabil
group by s.exercicio,
o.orgao,
fr.fonte,
fr.fonte_detalhe,
fr.nome;
// There are more six same sql with diferent parameter to return a list, so, this is only the first.
return (List<ReturnSqlResult>) entityManager.createNativeQuery(sql)
.setParameter("ano", ano)
.setParameter("mesInicial", mesInicial)
.setParameter("mesFinal", mesFinal)
.unwrap(NativeQuery.class)
.setResultTransformer(Transformers.aliasToBean(ReturnSqlResult.class))
.getResultList();
}
RETURN CLASS: ReturnSqlResult.class
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
#Data
public class ReturnSqlResult implements Serializable {
private Integer exercicio;
private Integer fonte;
private Integer fonteDet;
private String nomeFonte;
private BigDecimal atual;
private BigDecimal saldo;
}
EXPECTED: I hope that query return a list with these properties: EXERCICIO, FONTE, FONTEDET, NOMEFONTE, ATUAL, SALDO.
I have the following Oracle table definition.
CREATE TABLE "SIAS"."OPERATION_REG"
(
"ID" NUMBER CONSTRAINT "CT_OPERATION_REG_ID" NOT NULL ENABLE,
"OPERATION_NAME" VARCHAR2(30 BYTE),
"APPLICATION_NAME" VARCHAR2(30 BYTE),
"EXECUTION_DATE" DATE,
"EXECUTION_USER" VARCHAR2(80 BYTE),
"RESULT" VARCHAR2(20 BYTE),
CONSTRAINT "PK_OPERATION_REG_ID" PRIMARY KEY ("ID") USING INDEX PCTFREE 10
INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING STORAGE(INITIAL 65536 NEXT
1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST
GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SIAS_DAT" ENABLE
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING STORAGE
(
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE
0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT
CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "SIAS_DAT" ;
CREATE UNIQUE INDEX "SIAS"."IDX_OPERATION_REG_ID" ON "SIAS"."OPERATION_REG"
(
"ID"
)
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING STORAGE
(
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0
FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT
CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "SIAS_DAT" ;
CREATE OR REPLACE TRIGGER "SIAS"."BI_OPERATION_REG" BEFORE
INSERT ON OPERATION_REG REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW BEGIN
:NEW.ID := SEQ_OPERATION_REG.NEXTVAL;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR
(
-20255, 'ERROR EN TRIGGER BI_OPERATION_REG'
)
;
END;
/
ALTER TRIGGER "SIAS"."BI_OPERATION_REG" ENABLE;
I have this trigger enabled to auto generate the value of the ID column when a new row is being created.
create or replace
TRIGGER BI_OPERATION_REG BEFORE INSERT
ON OPERATION_REG
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
:NEW.ID := SEQ_OPERATION_REG.NEXTVAL;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR (-20255, 'ERROR EN TRIGGER BI_OPERATION_REG');
END;
This is the sequence definition to generate the values for ID
CREATE SEQUENCE "SIAS"."SEQ_OPERATION_REG" MINVALUE 1 MAXVALUE
999999999999999999999999999 INCREMENT BY 1 START WITH 37 NOCACHE NOORDER NOCYCLE ;
I have no control over the database, because the DBA team is out of my scope, so I have to deal with those definitions. I have created a JPA Entity that maps OPERATION_REG table. This is the ID property method mapping for column ID.
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "G1")
#SequenceGenerator(name = "G1", sequenceName = "SEQ_OPERATION_REG")
#Column(name = "ID")
public int getId() {
return id;
}
This is the full code of my entity mapping
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Collection;
#Entity
#Table(name = "OPERATION_REG")
public class OperationRegEntity extends BaseEntity {
private int id;
private String operationName;
private String applicationName;
private Timestamp executionDate;
private String executionUser;
private String result;
private Collection<TokenRegEntity> tokenRegsById;
private Collection<TraceRegEntity> traceRegsById;
#Id
#GeneratedValue(generator="select-generator")
#GenericGenerator(name="select-generator", strategy="select", parameters = #org.hibernate.annotations.Parameter(name="key", value="ID"))
// #GeneratedValue(strategy = GenerationType.AUTO, generator = "G1")
// #SequenceGenerator(name = "G1", sequenceName = "SEQ_OPERATION_REG")
#Column(name = "ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "OPERATION_NAME")
public String getOperationName() {
return operationName;
}
public void setOperationName(String operationName) {
this.operationName = operationName;
}
#Basic
#Column(name = "APPLICATION_NAME")
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
#Basic
#Column(name = "EXECUTION_DATE")
public Timestamp getExecutionDate() {
return executionDate;
}
public void setExecutionDate(Timestamp executionDate) {
this.executionDate = executionDate;
}
#Basic
#Column(name = "EXECUTION_USER")
public String getExecutionUser() {
return executionUser;
}
public void setExecutionUser(String executionUser) {
this.executionUser = executionUser;
}
#Basic
#Column(name = "RESULT")
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OperationRegEntity that = (OperationRegEntity) o;
if (id != that.id) return false;
if (applicationName != null ? !applicationName.equals(that.applicationName) : that.applicationName != null)
return false;
if (executionDate != null ? !executionDate.equals(that.executionDate) : that.executionDate != null)
return false;
if (executionUser != null ? !executionUser.equals(that.executionUser) : that.executionUser != null)
return false;
if (operationName != null ? !operationName.equals(that.operationName) : that.operationName != null)
return false;
if (result != null ? !result.equals(that.result) : that.result != null) return false;
return true;
}
#Override
public int hashCode() {
int result1 = id;
result1 = 31 * result1 + (operationName != null ? operationName.hashCode() : 0);
result1 = 31 * result1 + (applicationName != null ? applicationName.hashCode() : 0);
result1 = 31 * result1 + (executionDate != null ? executionDate.hashCode() : 0);
result1 = 31 * result1 + (executionUser != null ? executionUser.hashCode() : 0);
result1 = 31 * result1 + (result != null ? result.hashCode() : 0);
return result1;
}
#OneToMany(mappedBy = "operationRegByOperationRegId")
public Collection<TokenRegEntity> getTokenRegsById() {
return tokenRegsById;
}
public void setTokenRegsById(Collection<TokenRegEntity> tokenRegsById) {
this.tokenRegsById = tokenRegsById;
}
#OneToMany(mappedBy = "operationRegByOperationRegId")
public Collection<TraceRegEntity> getTraceRegsById() {
return traceRegsById;
}
public void setTraceRegsById(Collection<TraceRegEntity> traceRegsById) {
this.traceRegsById = traceRegsById;
}
}
I have a problem, because, when I create a new object and persist it on the database, I follow this strategy
#Autowired
OperationRegService operationregservice;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public OperationRegEntity createOperationReg(GenericRequestParameters parameters) {
OperationRegEntity oper = new OperationRegEntity();
oper.setApplicationName(parameters.getApplication());
oper.setExecutionUser(parameters.getApplicationUser());
oper.setOperationName(parameters.getSIASOperationName());
oper.setExecutionDate(new Timestamp(Calendar.getInstance().getTime().getTime()));
oper.setResult("INITIATED");
operationregservice.persist(oper);
return oper;
}
When I analyse the information of oper.getID(), the value is different from the actual value created in the database, in particular, always 1 point below. For example, the java entity has ID value of 34 and the table row entity has an ID value of 35, as if the sequence is getting called twice. Any ideas?
You shouldn't use a #SequenceGenerator, because that's used when you want Hibernate to call the sequence upon persisting an entity.
In your use case the database does the call so you need to use the select identifier generator strategy:
#Id
#GeneratedValue(generator="select-generator")
#GenericGenerator(name="select-generator",
strategy="select",
parameters = #org.hibernate.annotations.Parameter(name="key", value="ID")
)
#Column(name = "ID")
public int getId() {
return id;
}
Ok, I figure out the problem, and it was in the way the trigger generated the sequence. The key was to generate the sequence if no ID value was set already. That way, Hibernate will call the sequence, set the ID value, and the trigger will check if the value was set, if so, it will not call the sequence. If no value was set, then the trigger calls the sequence and sets the value
This is the valid trigger
create or replace
TRIGGER BI_OPERATION_REG BEFORE INSERT
ON OPERATION_REG
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF :NEW.ID IS NULL THEN SELECT SEQ_OPERATION_REG.NEXTVAL INTO :NEW.ID FROM dual; END IF;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR (-20255, 'ERROR EN TRIGGER BI_OPERATION_REG');
END;
I've got an issue with the select function of the Finder object by using ebean with Play! Framework (2.2.1).
I've got my table AnneePromotion :
CREATE TABLE AnneePromotion (
anneePromotion_ID INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('AnneePromotionSequence'),
anneePromotion_libelle INTEGER NOT NULL
);
My entity AnneePromotion :
#Entity
#Table(name = "AnneePromotion")
#SequenceGenerator(name = "AnneePromotionSequenceGenerator", sequenceName = "AnneePromotionSequence")
public class AnneePromotion extends Model {
/** serial ID */
private static final long serialVersionUID = -2072489268439045171L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AnneePromotionSequenceGenerator")
#Column(name = "anneePromotion_ID")
private Integer id;
#Column(name = "anneePromotion_libelle")
private String libelle;
public Integer getId() {
return id;
}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public static Finder<Integer, AnneePromotion> find = new Finder<Integer, AnneePromotion>(
Integer.class, AnneePromotion.class);
}
And when I try to use the select function in order to just have libelle :
List<AnneePromotion> listeDesAnneesdePromotion = AnneePromotionDao.find
.select("libelle").orderBy("libelle asc").findList();
for (AnneePromotion anneepromotion : listeDesAnneesdePromotion){
System.out.println(anneepromotion.getId()+" "+anneepromotion.getLibelle());
}
I received my objects with id and libelle columns :
1 2003
2 2004
3 2005
4 2006
5 2007
6 2008
7 2009
8 2010
9 2011
10 2012
11 2013
12 2014
13 2015
14 2016
I don't know with the select function doesn't work, if I made a stupid mistake or not :/
Hope you could help me.
Regards, Anthony.
That's common behavior of Ebean, reason is simple: you are asking for list of objects of concrete type, so it can't just return list of strings (without id) as it need to identify rows somehow.
The simplest solution is rewriting it to new list ie.
List<String> libelles = new ArrayList<>();
for (AnneePromotion anneepromotion : listeDesAnneesdePromotion){
libelles.add(anneepromotion.getLibelle());
}
Optionally you can also use Ebean's SqlQuery and then iterate through the list of SqlRow
to get the same libelles list.
I've got an Entity class named Fee. After performing an initial query, if more than one Fee is returned, I'd like to add some (WHERE) conditions only on the rows returned by the first query. Since a code snippet is better than a thousand words, here it is:
// Results of initial query
List<Fee> fees = queryFindFees.getResultList();
if (fees == null || fees.size() <= 0)
return null;
if (fees.size() == 1) {
Fee f = fees.get(0);
jpa.refresh(f);
return f;
}
// More than one fee found
String sqlBase = "SELECT f FROM Fee f WHERE f IN :fees";
String sqlComplete = sqlBase/* + " AND f.isValid = ?1"*/;
queryFindFees = jpa.createQuery(sqlComplete);
queryFindFees.setParameter("fees", fees);
// Commented out for test
// queryFindFees.setParameter(1, "Y");
List<Fee> specFees = queryFindFees.getResultList();
Now, since I'm actually asking for the EntityManager to return all the Fees already returned in the previous query, I would expect the same resultset. Instead the list specFees is always empty.
What am I doing wrong?
Thanks in advance,
Luca
EDIT 1: Details of Entity class Fee
#Entity
public class Fee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private long id;
#Column(nullable = false, length = 1)
private String isValid;
...
#Override
public boolean equals(Object arg0) {
if (!(arg0 instanceof Fee))
return false;
Fee f0 = (Fee) arg0;
return f0.getId() == this.getId();
}
}
The generated SQL (sqlComplete variable) is as expected:
SELECT f FROM Fee f WHERE f IN :fees
EDIT 2: As suggested by Deepak, using the collection of IDs works:
String sqlBase = "SELECT f FROM Fee f WHERE f.id IN :feesIds";
String sqlComplete = sqlBase/* + " AND f.isValid = ?1"*/;
List<Long> feesIds = new ArrayList<Long>();
for (Fee f : fees) {
feesIds.add(f.getId());
}
queryFindFees = jpa.createQuery(sqlComplete);
queryFindFees.setParameter("feesIds", feesIds);
Using this code the query works (returns all the original Fees), however if possible I would like to avoid using the for cycle because the number of Fee instances may be very large...
Looks like your overridden equals method is creating problem .Make your id Long Object and use the below overridden method .Alternatively u can use this query also
SELECT f FROM Fee f WHERE f.id IN :fees
this time your fees parameter will contain list of ids of Fee objects
#Entity
public class Fee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
#Column(nullable = false, length = 1)
private String isValid;
...
#Override
public boolean equals(Object arg0) {
if (!(arg0 instanceof Fee))
return false;
Fee f0 = (Fee) arg0;
return f0.getId().equals(this.getId());
}
}
In neo4j, how can I index by date and search in a date range. Also for times, I would like to search between 8am and 9am in a date range as well.
Index the dates and times as integer timestamps. Then you can easily search in an index for dates between other timestamps. You can also index the time part of the timestamp separately as another integer, allowing you to query for specific times between given dates.
Example:
The date and time to store is "2012-02-05 8:15 AM"
So in your index, store "timestamp=1328447700" and "time=815"
Now you want to query the index for all events between 2012-02-01 and 2012-02-10 that occurred from 8:00 am to 9:00 am. You do that by querying the index for
"timestamp>=1328072400 and timestamp<=1328936399 and time>=800 and time<=900"
The exact syntax for doing this depends on how you are connecting to Neo4j (REST or embedded) and which programming language you are using. But the idea is the same in any case.
There's a convenient org.neo4j.index.lucene.LuceneTimeline which does this (using an integrated lucene index in neo4j).
This is an extension to Josh Adell's answer. For readability, I suggest having two date and time integer fields like
date:19970716 (YYYYMMDD)
time:203045000 (HHmmssuuu): last three digits for microseconds.
The int datatype can store upto 2147483647. If you are feeling adventurous, the long datatype can store upto 9223372036854775807.
http://docs.neo4j.org/chunked/stable/graphdb-neo4j-properties.html
Inspired from ISO 8601 timestamps like 1997-07-16T19:20:30.45Z.
Disclaimer: I have only minimal experience with Neo4J.
with Spring data neo4j
public List<Email> getAllEmailData(Date startDate, Date endDate) {
List<Email> list = new ArrayList<Email>();
if (startDate == null || endDate == null) {
return null;
}
long first = ConversionsUtils.convertDateToLong(startDate);
long second = ConversionsUtils.convertDateToLong(endDate);
try {
list = emailRepository.searchAllData(first, second);
// System.out.println("List size " +list.size());
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
#Query(
"START email=node:__types__(className='com.backend.core.neo.entities.Email') "
+ "WHERE email.searchDate > {0} and email.searchDate < {1}"
+ "RETURN email")
List<Email> searchAllData(long startDate, long endDate);
email entity
#NodeEntity
public class Email implements Serializable {
private static final long serialVersionUID = 1L;
public static final String CC = "CC";
public static final String TO = "TO";
#GraphId
private Long id;
#GraphProperty
private Long senderId;
#GraphProperty
private String subject;
#Indexed
// #GraphProperty(propertyType = java.util.Date.class)
private String dateSent;
#Indexed
private long searchDate;
#GraphProperty
private String emailTxt;
#GraphProperty
private String emailHtml;
#GraphProperty
private String emailId;
//mail to
#Fetch
#RelatedTo(elementClass = User.class, type = TO, direction = Direction.OUTGOING)
private Set<User> intoUsers;
//mail shared
#Fetch
#RelatedTo(elementClass = User.class, type = CC, direction = Direction.OUTGOING)
private Set<User> sharedUsers;