Ho una query SELECT leggermente più articolata del solito che ho già testato sul query tools di PostgreSQL e che funziona alla perfezione. Vorrei implementare questa query dentro la mia classe @Repository. Il metodo che ho scritto restituisce sempre null e non so dove sia il problema. Il mio oggetto RowMapper a differenza di quelli che ho scritto in precedenza non si riferisce ad una reale tabella del database perché nella SELECT c’è anche una INNER JOIN. Non vorrei fosse questo il problema. Ho stampato la query prodotta dal metodo con i punti interrogativi nella console, poi ho copiato le stringe sul query tools dell’IDE, infine sostituito i ‘?‘ con i valori di mio interesse e tutto funziona a meraviglia. Non so se sbaglio a scrivere l’oggetto RowMapper oppure l’oggetto Repository.
@Transactional(readOnly=true)
public List<EventoConNomiUtente> cercaEventi(CercaEventi cercaEventi) {
try{
// Si pongono pari a null i parametri di ricerca non idonei.
if(cercaEventi==null) {
return null;
}
if(cercaEventi.getId_utente()==null || cercaEventi.getId_utente()<=0) {
cercaEventi.setId_utente(null);
}
if(cercaEventi.getNome_utente()==null || cercaEventi.getNome_utente().isBlank()) {
cercaEventi.setNome_utente(null);
}
if(cercaEventi.getTitolo()==null || cercaEventi.getTitolo().isBlank()) {
cercaEventi.setTitolo(null);
}
if(cercaEventi.getDescrizione()==null || cercaEventi.getDescrizione().isBlank()) {
cercaEventi.setDescrizione(null);
}
if(cercaEventi.getLuogo()==null || cercaEventi.getLuogo().isBlank()) {
cercaEventi.setLuogo(null);
}
if(cercaEventi.getStato()==null || cercaEventi.getStato().isBlank()) {
cercaEventi.setStato(null);
}
if(
cercaEventi.getOrdine()==null ||
!(cercaEventi.getOrdine().equals("ASC") || cercaEventi.getOrdine().equals("DESC"))
) {
cercaEventi.setOrdine(null);
}
if(cercaEventi.getNumero_righe()==null || cercaEventi.getNumero_righe()<=0) {
cercaEventi.setNumero_righe(null);
}
// System.out.println(cercaEventi.toString());
// Si crea una stringa variabile contenente la query.
StringBuilder select = new StringBuilder();
select.append("CREATE OR REPLACE FUNCTION cercaeventi(\n");
select.append("id_utente_cercato BIGINT,\n");
select.append("nome_utente_cercato CHARACTER VARYING,\n");
select.append("titolo_cercato CHARACTER VARYING,\n");
select.append("descrizione_cercata TEXT,\n");
select.append("luogo_cercato CHARACTER VARYING,\n");
select.append("data_inferiore_compresa_cercata TIMESTAMP WITH TIME ZONE,\n");
select.append("data_superiore_esclusa_cercata TIMESTAMP WITH TIME ZONE,\n");
select.append("stato_cercato CHARACTER VARYING,\n");
select.append("ordine CHARACTER VARYING, -- 'ASC' oppure 'DESC'\n");
select.append("numero_righe BIGINT\n");
select.append(")\n");
select.append("RETURNS TABLE (\n");
select.append("id_evento BIGINT,\n");
select.append("id_utente BIGINT,\n");
select.append("nome_utente CHARACTER VARYING,\n");
select.append("titolo_evento CHARACTER VARYING,\n");
select.append("descrizione_evento TEXT,\n");
select.append("luogo_evento CHARACTER VARYING,\n");
select.append("data_evento TIMESTAMP WITH TIME ZONE,\n");
select.append("stato_evento CHARACTER VARYING\n");
select.append(")\n");
select.append("LANGUAGE PLPGSQL\n");
select.append("AS\n");
select.append("$$\n");
select.append("BEGIN\n");
select.append("IF ordine = 'ASC' THEN\n");
select.append("RETURN QUERY\n");
select.append("SELECT\n");
select.append("eventi.id,\n");
select.append("eventi.id_utente,\n");
select.append("utenti.nome,\n");
select.append("eventi.titolo,\n");
select.append("eventi.descrizione,\n");
select.append("eventi.luogo,\n");
select.append("eventi.data,\n");
select.append("eventi.stato\n");
select.append("FROM\n");
select.append("eventi\n");
select.append("INNER JOIN utenti ON eventi.id_utente = utenti.id\n");
select.append("WHERE 1=1\n");
select.append("AND (\n");
select.append("(id_utente_cercato IS NULL) OR\n");
select.append("(eventi.id_utente = id_utente_cercato)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(nome_utente_cercato IS NULL) OR\n");
select.append("(utenti.nome = nome_utente_cercato AND eventi.id_utente = utenti.id)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(titolo_cercato IS NULL) OR\n");
select.append("(LOWER(eventi.titolo) LIKE LOWER(CONCAT('%',titolo_cercato,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(descrizione_cercata IS NULL) OR\n");
select.append("(LOWER(eventi.descrizione) LIKE LOWER(CONCAT('%',descrizione_cercata,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(luogo_cercato IS NULL) OR\n");
select.append("(LOWER(eventi.luogo) LIKE LOWER(CONCAT('%',luogo_cercato,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(data_inferiore_compresa_cercata IS NULL) OR\n");
select.append("(eventi.data >= data_inferiore_compresa_cercata)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(data_superiore_esclusa_cercata IS NULL) OR\n");
select.append("(eventi.data < data_superiore_esclusa_cercata )\n");
select.append(")\n");
select.append("AND (\n");
select.append("(stato_cercato IS NULL) OR\n");
select.append("(eventi.stato = stato_cercato)\n");
select.append(")\n");
select.append("ORDER BY eventi.data ASC\n");
select.append("LIMIT numero_righe;\n");
select.append("ELSIF ordine = 'DESC' THEN\n");
select.append("RETURN QUERY\n");
select.append("SELECT\n");
select.append("eventi.id,\n");
select.append("eventi.id_utente,\n");
select.append("utenti.nome, -- questa colonna viene importata dalla tabella degli utenti\n");
select.append("eventi.titolo,\n");
select.append("eventi.descrizione,\n");
select.append("eventi.luogo,\n");
select.append("eventi.data,\n");
select.append("eventi.stato\n");
select.append("FROM\n");
select.append("eventi\n");
select.append("INNER JOIN utenti ON eventi.id_utente = utenti.id\n");
select.append("WHERE 1=1\n");
select.append("AND (\n");
select.append("(id_utente_cercato IS NULL) OR\n");
select.append("(eventi.id_utente = id_utente_cercato)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(nome_utente_cercato IS NULL) OR\n");
select.append("(utenti.nome = nome_utente_cercato AND eventi.id_utente = utenti.id)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(titolo_cercato IS NULL) OR\n");
select.append("(LOWER(eventi.titolo) LIKE LOWER(CONCAT('%',titolo_cercato,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(descrizione_cercata IS NULL) OR\n");
select.append("(LOWER(eventi.descrizione) LIKE LOWER(CONCAT('%',descrizione_cercata,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(luogo_cercato IS NULL) OR\n");
select.append("(LOWER(eventi.luogo) LIKE LOWER(CONCAT('%',luogo_cercato,'%')))\n");
select.append(")\n");
select.append("AND (\n");
select.append("(data_inferiore_compresa_cercata IS NULL) OR\n");
select.append("(eventi.data >= data_inferiore_compresa_cercata)\n");
select.append(")\n");
select.append("AND (\n");
select.append("(data_superiore_esclusa_cercata IS NULL) OR\n");
select.append("(eventi.data < data_superiore_esclusa_cercata )\n");
select.append(")\n");
select.append("AND (\n");
select.append("(stato_cercato IS NULL) OR\n");
select.append("(eventi.stato = stato_cercato)\n");
select.append(")\n");
select.append("ORDER BY eventi.data DESC\n");
select.append("LIMIT numero_righe;\n");
select.append("ELSE\n");
select.append("null;\n");
select.append("END IF;\n");
select.append("END;\n");
select.append("$$;\n");
select.append("SELECT * FROM cercaeventi(\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?,\n");
select.append("?\n");
select.append(");\n");
// Si converte in stringa statica l'oggetto precedente.
String sql = select.toString();
// System.out.println(sql);
return jdbcTemplate.query(
sql,
new EventoConNomiUtenteRowMapper(),
cercaEventi.getId_utente(),
cercaEventi.getNome_utente(),
cercaEventi.getTitolo(),
cercaEventi.getDescrizione(),
cercaEventi.getLuogo(),
cercaEventi.getDataOraInizialeInclusa(),
cercaEventi.getDataOraFinaleEsclusa(),
cercaEventi.getStato(),
cercaEventi.getOrdine(),
cercaEventi.getNumero_righe()
);
}catch (Exception e){
return null;
}
}
public class EventoConNomiUtenteRowMapper implements RowMapper<EventoConNomiUtente> {
GestioneDataOra gestioneDataOra = new GestioneDataOra();
@Override
public EventoConNomiUtente mapRow(ResultSet rs, int rowNum) throws SQLException {
EventoConNomiUtente eventoConNomiUtente = new EventoConNomiUtente();
eventoConNomiUtente.setId_evento(rs.getLong("id_evento"));
eventoConNomiUtente.setId_utente(rs.getLong("id_utente"));
eventoConNomiUtente.setNome_utente(rs.getString("nome_utente"));
eventoConNomiUtente.setTitolo_evento(rs.getString("titolo_evento"));
eventoConNomiUtente.setDescrizione_evento(rs.getString("descrizione_evento"));
eventoConNomiUtente.setLuogo_evento(rs.getString("luogo_evento"));
eventoConNomiUtente.setData_evento(
gestioneDataOra.daTimestampAdOffsetDateTime(rs.getTimestamp("data_evento"))
);
eventoConNomiUtente.setStato_evento(rs.getString("stato_evento"));
return eventoConNomiUtente;
}
}
public class EventoConNomiUtente {
private Long id_evento;
private Long id_utente;
private String nome_utente;
private String titolo_evento;
private String descrizione_evento;
private String luogo_evento;
private OffsetDateTime data_evento;
private String stato_evento;
public EventoConNomiUtente() {}
public EventoConNomiUtente(Long id_evento, Long id_utente, String nome_utente, String titolo_evento,
String descrizione_evento, String luogo_evento, OffsetDateTime data_evento,
String stato_evento) {
this.id_evento = id_evento;
this.id_utente = id_utente;
this.nome_utente = nome_utente;
this.titolo_evento = titolo_evento;
this.descrizione_evento = descrizione_evento;
this.luogo_evento = luogo_evento;
this.data_evento = data_evento;
this.stato_evento = stato_evento;
}
public Long getId_evento() {
return id_evento;
}
public void setId_evento(Long id_evento) {
this.id_evento = id_evento;
}
public Long getId_utente() {
return id_utente;
}
public void setId_utente(Long id_utente) {
this.id_utente = id_utente;
}
public String getNome_utente() {
return nome_utente;
}
public void setNome_utente(String nome_utente) {
this.nome_utente = nome_utente;
}
public String getTitolo_evento() {
return titolo_evento;
}
public void setTitolo_evento(String titolo_evento) {
this.titolo_evento = titolo_evento;
}
public String getDescrizione_evento() {
return descrizione_evento;
}
public void setDescrizione_evento(String descrizione_evento) {
this.descrizione_evento = descrizione_evento;
}
public String getLuogo_evento() {
return luogo_evento;
}
public void setLuogo_evento(String luogo_evento) {
this.luogo_evento = luogo_evento;
}
public OffsetDateTime getData_evento() {
return data_evento;
}
public void setData_evento(OffsetDateTime data_evento) {
this.data_evento = data_evento;
}
public String getStato_evento() {
return stato_evento;
}
public void setStato_evento(String stato_evento) {
this.stato_evento = stato_evento;
}
// Il metodo toString() serve per stampare in console l'oggetto;
@Override
public String toString() {
return "Oggetto di tipo 'CercaEventi' contenente:" +
"\n id_evento = " + id_evento +
"\n id_utente = " + id_utente +
"\n nome_utente = " + nome_utente +
"\n titolo_evento = " + titolo_evento +
"\n descrizione_evento = " + descrizione_evento +
"\n luogo_evento = " + luogo_evento +
"\n data_evento = " + data_evento +
"\n stato_evento = " + stato_evento;
}
}
public class CercaEventi {
private Long id_utente;
private String nome_utente;
private String titolo;
private String descrizione;
private String luogo;
// Vedi GestioneEventi.java per dettagli sull'annotazione.
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime dataOraInizialeInclusa;
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime dataOraFinaleEsclusa;
private String stato;
private String ordine;
private Long numero_righe;
public CercaEventi() {
}
public CercaEventi(Long id_utente, String nome_utente, String titolo, String descrizione, String luogo,
LocalDateTime dataOraInizialeInclusa, LocalDateTime dataOraFinaleEsclusa, String stato,
String ordine, Long numero_righe) {
this.id_utente = id_utente;
this.nome_utente = nome_utente;
this.titolo = titolo;
this.descrizione = descrizione;
this.luogo = luogo;
this.dataOraInizialeInclusa = dataOraInizialeInclusa;
this.dataOraFinaleEsclusa = dataOraFinaleEsclusa;
this.stato = stato;
this.ordine = ordine;
this.numero_righe = numero_righe;
}
public Long getId_utente() {
return id_utente;
}
public void setId_utente(Long id_utente) {
this.id_utente = id_utente;
}
public String getNome_utente() {
return nome_utente;
}
public void setNome_utente(String nome_utente) {
this.nome_utente = nome_utente;
}
public String getTitolo() {
return titolo;
}
public void setTitolo(String titolo) {
this.titolo = titolo;
}
public String getDescrizione() {
return descrizione;
}
public void setDescrizione(String descrizione) {
this.descrizione = descrizione;
}
public String getLuogo() {
return luogo;
}
public void setLuogo(String luogo) {
this.luogo = luogo;
}
public LocalDateTime getDataOraInizialeInclusa() {
return dataOraInizialeInclusa;
}
public void setDataOraInizialeInclusa(LocalDateTime dataOraInizialeInclusa) {
this.dataOraInizialeInclusa = dataOraInizialeInclusa;
}
public LocalDateTime getDataOraFinaleEsclusa() {
return dataOraFinaleEsclusa;
}
public void setDataOraFinaleEsclusa(LocalDateTime dataOraFinaleEsclusa) {
this.dataOraFinaleEsclusa = dataOraFinaleEsclusa;
}
public String getStato() {
return stato;
}
public void setStato(String stato) {
this.stato = stato;
}
public String getOrdine() {
return ordine;
}
public void setOrdine(String ordine) {
this.ordine = ordine;
}
public Long getNumero_righe() {
return numero_righe;
}
public void setNumero_righe(Long numero_righe) {
this.numero_righe = numero_righe;
}
// Il metodo toString() serve per stampare in console l'oggetto;
@Override
public String toString() {
return "Oggetto di tipo 'CercaEventi' contenente:" +
"\n id_utente = " + id_utente +
"\n nome_utente = " + nome_utente +
"\n titolo = " + titolo +
"\n descrizione = " + descrizione +
"\n luogo = " + luogo +
"\n dataOraInizialeInclusa = " + dataOraInizialeInclusa +
"\n dataOraFinaleEsclusa = " + dataOraFinaleEsclusa +
"\n stato = " + stato +
"\n ordine = " + ordine +
"\n numero_righe = " + numero_righe;
}
}
CREATE OR REPLACE FUNCTION cercaeventi(
id_utente_cercato BIGINT,
nome_utente_cercato CHARACTER VARYING,
titolo_cercato CHARACTER VARYING,
descrizione_cercata TEXT,
luogo_cercato CHARACTER VARYING,
data_inferiore_compresa_cercata TIMESTAMP WITH TIME ZONE,
data_superiore_esclusa_cercata TIMESTAMP WITH TIME ZONE,
stato_cercato CHARACTER VARYING,
ordine CHARACTER VARYING, -- 'ASC' oppure 'DESC'
numero_righe BIGINT
)
RETURNS TABLE (
id_evento BIGINT,
id_utente BIGINT,
nome_utente CHARACTER VARYING,
titolo_evento CHARACTER VARYING,
descrizione_evento TEXT,
luogo_evento CHARACTER VARYING,
data_evento TIMESTAMP WITH TIME ZONE,
stato_evento CHARACTER VARYING
)
LANGUAGE PLPGSQL
AS
$$
BEGIN
IF ordine = 'ASC' THEN
RETURN QUERY
SELECT
eventi.id,
eventi.id_utente,
utenti.nome,
eventi.titolo,
eventi.descrizione,
eventi.luogo,
eventi.data,
eventi.stato
FROM
eventi
INNER JOIN utenti ON eventi.id_utente = utenti.id
WHERE 1=1
AND (
(id_utente_cercato IS NULL) OR
(eventi.id_utente = id_utente_cercato)
)
AND (
(nome_utente_cercato IS NULL) OR
(utenti.nome = nome_utente_cercato AND eventi.id_utente = utenti.id)
)
AND (
(titolo_cercato IS NULL) OR
(LOWER(eventi.titolo) LIKE LOWER(CONCAT('%',titolo_cercato,'%')))
)
AND (
(descrizione_cercata IS NULL) OR
(LOWER(eventi.descrizione) LIKE LOWER(CONCAT('%',descrizione_cercata,'%')))
)
AND (
(luogo_cercato IS NULL) OR
(LOWER(eventi.luogo) LIKE LOWER(CONCAT('%',luogo_cercato,'%')))
)
AND (
(data_inferiore_compresa_cercata IS NULL) OR
(eventi.data >= data_inferiore_compresa_cercata)
)
AND (
(data_superiore_esclusa_cercata IS NULL) OR
(eventi.data < data_superiore_esclusa_cercata )
)
AND (
(stato_cercato IS NULL) OR
(eventi.stato = stato_cercato)
)
ORDER BY eventi.data ASC
LIMIT numero_righe;
ELSIF ordine = 'DESC' THEN
RETURN QUERY
SELECT
eventi.id,
eventi.id_utente,
utenti.nome, -- questa colonna viene importata dalla tabella degli utenti
eventi.titolo,
eventi.descrizione,
eventi.luogo,
eventi.data,
eventi.stato
FROM
eventi
INNER JOIN utenti ON eventi.id_utente = utenti.id
WHERE 1=1
AND (
(id_utente_cercato IS NULL) OR
(eventi.id_utente = id_utente_cercato)
)
AND (
(nome_utente_cercato IS NULL) OR
(utenti.nome = nome_utente_cercato AND eventi.id_utente = utenti.id)
)
AND (
(titolo_cercato IS NULL) OR
(LOWER(eventi.titolo) LIKE LOWER(CONCAT('%',titolo_cercato,'%')))
)
AND (
(descrizione_cercata IS NULL) OR
(LOWER(eventi.descrizione) LIKE LOWER(CONCAT('%',descrizione_cercata,'%')))
)
AND (
(luogo_cercato IS NULL) OR
(LOWER(eventi.luogo) LIKE LOWER(CONCAT('%',luogo_cercato,'%')))
)
AND (
(data_inferiore_compresa_cercata IS NULL) OR
(eventi.data >= data_inferiore_compresa_cercata)
)
AND (
(data_superiore_esclusa_cercata IS NULL) OR
(eventi.data < data_superiore_esclusa_cercata )
)
AND (
(stato_cercato IS NULL) OR
(eventi.stato = stato_cercato)
)
ORDER BY eventi.data DESC
LIMIT numero_righe;
ELSE
null;
END IF;
END;
$$;
SELECT * FROM cercaeventi(
6,
null,
null,
null,
null,
null,
null,
null,
'DESC',
5
);