Creato da pastuweb.com
Share My Page
My Social Accounts
Account FaceBook Account LinkedIn Account Twitter Account Google Plus Account Git Hub

A volte, usando Liferay, potrebbe capitare l'esigenza di dover creare una query abbastanza complessa, magari con diversi join, raggruppamenti, partizion by ecc.  Questo tipo di query cade nelle query "Custom".

Come prima cosa vediamo il service.xml:

<entity  name="Utenti"   local-service="true" remote-service="true"  
data-source="anotherDataSource" session-factory="anotherSessionFactory">
 
    <!-- PK Fields -->
    <column name="id_utente" type="long"  primary="true"   />
 
    <!-- Other Fields -->
    <column name="nome" type="String"   />
    <column name="cognome" type="String" />
 
<order by="asc">
      <order-column name="id_utente" />
    </order>
 
</entity>

 

Come si può notare ho usato un DataSource e un SessionFactory personalizzato, perchè nel mio progetto accedo sia al database di Liferay sia ad un secondo database di supporto. I beans: "anotherDataSource" e "anotherSessionFactory" vengono specificati in ext-spring.xml.

Tornando a noi, una volta definita la entity ed eseguito il build-service possiamo iniziare a personalizzare le classi implementative e a crearne di nuove.

Ho creato un package in cui raggruppo le classi che utilizzano la funzionalità di Custom SQL Query:

com.appuntivari.custom.service

  • CustomService.java (interfaccia)
  • CustomServiceImpl.java (parte implementativa)

Leggete i commenti della classe CustomServiceImpl.jav, così ve ne farete un idea.

public class CustomServiceImpl implements CustomService {
 
/**
* CustomServiceImpl: 
* serve per interfacciarsi con le procedure che utilizzano Query SQL custom.
* Tutto l' SQL Custom è in:
* -> custom-sql/default.xml
* -> custom-sql/custom_sql_123456.xml
* Le classi usate indirettamente sono:
* -> com.appuntivari.custom.service.CustomService.java
* -> com.appuntivari.service.impl.xxxxxxxxLocalServiceImpl.java
* -> com.appuntivari.service.persistence.xxxxxxxxFinderImpl.java
* (dove xxxxxxxx = "name" della "entity" del service.xml)
* IMPORTANTE:
* qui DEVONO essere implementate solo procedure che utilizzano indirettamente 
* classi con la nomenclatura xxxxxxxFinderImpl.java ossia procedure che vanno 
* ad utilizzare il Custom SQL.
*/
 
@SuppressWarnings("unchecked")
public List<Object[]> getElencoNomeCognomeUtenti(){
return UtentiLocalServiceUtil.getElencoNomeCognomeUtenti();
}
 
}

 

Ora andiamo ad implementare tutto il resto:

Per prima cosa creiamo una nuova cartella sotto il path: docroot/WEB-INF/src, la nuova cartella si deve chiamare custom-sql e deve essere di tipo sorgente.

Dentro a "custom-sql" creiamo due descrittori .xml:

  • default.xml
<?xml version="1.0" encoding="UTF-8"?>
<custom-sql>
    <sql file="custom-sql/custom_sql_utenti.xml" />
</custom-sql> 

 

  • custom_sql_utenti.xml (in questo xml ci andranno tutte le query riferite agli utenti e non solo, a vostra discrezione)
<?xml version="1.0" encoding="UTF-8"?>
<custom-sql>
 
<sql id="com.appuntivari.service.persistence.UtentiFinder.sqlSoloNomeCognomeUtenti">
<![CDATA[
SELECT nome, cognome FROM PW_UTENTI
 ]]>
</sql>
 
<sql id="com.appuntivari.service.persistence.UtentiFinder.sqlSoloNomeCognomeUtentiByCognome">
<![CDATA[
SELECT nome, cognome FROM PW_UTENTI WHERE cognome = ?
 ]]>
</sql>
 
</custom-sql>
 
Ora creaiamo la classe più importante: UtentiFinderImpl.java sotto il package com.appuntivari.service.persistence:
Questa classe implementa la logica per eseguire e estrapolare i dati/record dalla query precedentemente definita.
 
public class UtentiFinderImpl extends BasePersistenceImpl implements UtentiFinder{
 
public static String SQL_NOME_COGNOME_UTENTI =
UtentiFinder.class.getName()+".sqlSoloNomeCognomeUtenti";
public static Log log = LogFactory.getLog("UtentiFinderImpl");
 
public static String SQL_NOME_COGNOME_UTENTI_BY_COGN =
UtentiFinder.class.getName()+".sqlSoloNomeCognomeUtentiByCognome";
public static Log log = LogFactory.getLog("UtentiFinderImpl");
 
public List<Object[]> getElencoNomeCognomeUtenti(){
List<Object[]> results = null;
Session session = null;
 
try{
 
session = openSession();
 
String sql = CustomSQLUtil.get(SQL_NOME_COGNOME_UTENTI );
SQLQuery q = session.createSQLQuery(sql);
 
q.addScalar("nome", Type.STRING);
q.addScalar("cognome", Type.STRING);
 
results = (List<Object[]>) QueryUtil.list(q, getDialect(), 0, q.list().size());
 
log.info("#### Size = "+q.list().size());
 
/* Test:
for(Object[] item: results){
log.info("Cod = "+item[0]+" - Descr = "+item[1]);
   }
   */
 
} catch (Exception e) {
            System.out.println("Exception : Finder custom");
            e.printStackTrace();
        } finally {
            closeSession(session);
        }
 
 
return results;
}
 
public List<Object[]> getElencoNomeCognomeUtentiByCognome(String parCognome){
List<Object[]> results = null;
Session session = null;
 
try{
 
session = openSession();
 
String sql = CustomSQLUtil.get(SQL_NOME_COGNOME_UTENTI_BY_COGN );
SQLQuery q = session.createSQLQuery(sql);
 
q.addScalar("nome", Type.STRING);
q.addScalar("cognome", Type.STRING);
 
QueryPos qPos = QueryPos.getInstance(q); //setto il parametro della query
qPos.add(parCognome);
 
results = (List<Object[]>) QueryUtil.list(q, getDialect(), 0, q.list().size());
 
log.info("#### Size = "+q.list().size());
 
/* Test:
for(Object[] item: results){
log.info("Cod = "+item[0]+" - Descr = "+item[1]);
   }
   */
 
} catch (Exception e) {
            System.out.println("Exception : Finder custom");
            e.printStackTrace();
        } finally {
            closeSession(session);
        }
 
 
return results;
}
 
}
 
Rimane solo più una classe da implementare, quella che espone il metodo al nostro package personalizzato: UtentiLocalServiceImpl.java nel package com.appuntivari.service.impl.
 
 
public class UtentiLocalServiceImpl extends UtentiLocalServiceBaseImpl {
/*
* NOTE FOR DEVELOPERS:
*
* Never reference this interface directly. Always use {@link com.appuntivari.service.UtentiLocalServiceUtil}
to access the grup misure local service.
*/
public List<Object[]> getElencoNomeCognomeUtenti(){
return UtentiFinderUtil.getElencoNomeCognomeUtenti();
}
 
public List<Object[]> getElencoNomeCognomeUtentiByCognome(String parCognome){
return UtentiFinderUtil.getElencoNomeCognomeUtenti(parCognome);
}
}
 
 
Ok. Ora facciamo partire di nuovo il build-service del SDK di Liferay. Verranno generate le interfacce delle classi appena create.
 
Ora in una JSP/portlet possiamo recuperare i dati di quella query, in questo caso vengono recuperari solo i cognomi item[1]:
 
<p>
<strong>Lista descrizioni mappate:</strong><br><br>
<%
CustomServiceImpl myCusotmService = new CustomServiceImpl();
   List<Object[]> lista = myCusotmService .getElencoNomeCognomeUtenti();
   for(Object[] item: lista){
%>
<%=item[1]%>;
<%
%>
</p>
 
Average (1 Vote)
The average rating is 5.0 stars out of 5.