Come caricare un file "xxx.hbm.cfg" in un progetto JPA 2.0?
-
27-10-2019 - |
Domanda
Ho appena avviato un'applicazione a molla con Hibernate come fornitore JPA2.0. Sto usando i barattoli come segue:
Hibernate-core-3.6.4.final.jar
Hibernate-Commons-Annitations-3.2.0.jar
Hibernate-EntityManager-3.6.4.final.jar
hibernate-jpa --2.0-api-1.0.0.final.jar
Hibernate-Validator-4.1.0.final.jar
Sto usando annotazioni per gestire l'aspetto transazionale dell'applicazione, nessun problema lì.
Ma ci sono altre parti dell'applicazione che richiedono query molto complesse e il modo in cui l'ho gestito in ibernazione prima era creare un file di mappatura ad es. Pojo. Non una @enty. Funziona bene.
Tuttavia, attraverso un'altra domanda che ho pubblicato in precedenza, ho scoperto che in JPA 2.0 non puoi avere domande mappate su un pojo, tutto deve essere mappato su una @enty (una tabella DB no?).
Quindi la mia domanda è la seguente:
C'è un modo in cui posso avere il mio 'mybigdwquery.hbm.xml' File caricato nella mia persistenza.xml come hbm.xml in modo da poter chiamare la query nominata?
La mia persistenza.xml è la seguente:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> -->
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
</properties>
</persistence-unit>
</persistence>
Il file di cui ho bisogno caricato:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="edu.kdc.visioncards.pojo">
<class name="AttendanceBreakDown">
<cache usage="read-only" />
<id name="studentName"/>
<property name="pupilId"></property>
<property name="enrollmentStatus"></property>
<property name="attendanceLevel"></property>
<property name="attendanceDays"></property>
<property name="authorizedAbsences"></property>
<property name="unexcusedAbsences"></property>
<property name="excusedAbsences"></property>
<property name="tardies"></property>
<property name="attendancePct"></property>
</class>
<sql-query name="attendanceDetailsBySchoolAndGradingPeriod">
<return alias="attSchGr" class="edu.kdc.visioncards.pojo.AttendanceBreakDown">
<return-property name="studentName" column="student_name"/>
<return-property name="pupilId" column="student_id"/>
<return-property name="enrollmentStatus" column="enrollment_status"/>
<return-property name="attendanceLevel" column="attendance_Level"/>
<return-property name="attendanceDays" column="attendance_days"/>
<return-property name="authorizedAbsences" column="auth_abs"/>
<return-property name="unexcusedAbsences" column="unx_abs"/>
<return-property name="excusedAbsences" column="x_abs"/>
<return-property name="tardies" column="tardies"/>
<return-property name="attendancePct" column="att_pct"/>
</return>
select
a.student_name
,a.student_id
,a.enrollment_status
,a.attendance_days
,a.Attendance_Level
,b.authorized_absences as auth_abs
,nvl(c.unx_abs,0) as unx_abs
,nvl(d.x_abs, 0) as x_abs
,nvl(e.tardies, 0) as tardies
,a.att_pct
from
(select
s.student_name
,s.student_id
,s.student_activity_indicator as enrollment_status
,sum(fas.attendance_days) as attendance_days
,round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) as att_pct
,case when(round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) <= 87)
then 'Intervene'
when(round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) >87 and
round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) <= 89.9)
then 'Concern'
when(round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) >=90 and
round((sum(fas.attendance_value) / sum(fas.attendance_days))* 100,2) <= 95)
then 'Baseline'
else 'Is Clean'
end AS Attendance_Level
from K12INTEL_DW.ftbl_attendance_stumonabssum fas
inner join k12intel_dw.dtbl_students s
on fas.student_key = s.student_key
inner join K12INTEL_DW.dtbl_schools ds
on fas.school_key = ds.school_key
inner join k12intel_dw.dtbl_school_dates dsd
on fas.school_dates_key = dsd.school_dates_key
where dsd.rolling_local_school_yr_number = 0
and ds.school_code = ?
and s.student_activity_indicator = 'Active'
and fas.LOCAL_GRADING_PERIOD = ?
and s.student_current_grade_level = ?
group by s.student_id, s.student_name, s.student_activity_indicator
having (sum(fas.attendance_value) / sum(fas.attendance_days)) < .95
) a
inner join
(select t.student_id
,sum(t.auth_abs) as authorized_absences
from(
select dstud.student_id
,case when(fas.excused_authorized) in ('NA', 'No')
then 0 else 1
end as auth_abs
from K12INTEL_DW.ftbl_attendance_stumonabssum fas
inner join K12INTEL_DW.dtbl_schools ds
on fas.school_key = ds.school_key
inner join k12intel_dw.dtbl_students dstud
on dstud.student_key = fas.student_key
inner join k12intel_dw.dtbl_school_dates dsd
on dsd.school_dates_key = fas.school_dates_key
where dsd.rolling_local_school_yr_number = 0
and dstud.student_activity_indicator = 'Active'
and ds.school_code = ?
and fas.LOCAL_GRADING_PERIOD = ?
and dstud.student_current_grade_level = ?
) t
group by t.student_id)b
on b.student_id = a.student_id
left outer join
( select dstud.student_id,
count(fas.excused_absence) as unx_abs
from K12INTEL_DW.ftbl_attendance_stumonabssum fas
inner join K12INTEL_DW.dtbl_schools ds
on fas.school_key = ds.school_key
inner join k12intel_dw.dtbl_students dstud
on dstud.student_key = fas.student_key
inner join k12intel_dw.dtbl_school_dates dsd
on dsd.school_dates_key = fas.school_dates_key
where dsd.rolling_local_school_yr_number = 0
and dstud.student_activity_indicator = 'Active'
and fas.excused_absence = 'Un-excused absence'
and ds.school_code = ?
and fas.LOCAL_GRADING_PERIOD = ?
and dstud.student_current_grade_level = ?
group by dstud.student_id
) c
on c.student_id = a.student_id
left outer join
(select dstud.student_id, count(fas.excused_absence) as x_abs
from K12INTEL_DW.ftbl_attendance_stumonabssum fas
inner join K12INTEL_DW.dtbl_schools ds
on fas.school_key = ds.school_key
inner join k12intel_dw.dtbl_students dstud
on dstud.student_key = fas.student_key
inner join k12intel_dw.dtbl_school_dates dsd
on dsd.school_dates_key = fas.school_dates_key
where dsd.rolling_local_school_yr_number = 0
and dstud.student_activity_indicator = 'Active'
and fas.excused_absence = 'Excused absence'
and ds.school_code = ?
and fas.LOCAL_GRADING_PERIOD = ?
and dstud.student_current_grade_level = ?
group by dstud.student_id) d
on d.student_id = a.student_id
left outer join
(select s.student_id
,sum(a.attendance_value) tardies
from k12intel_dw.ftbl_attendance a
inner join k12intel_dw.dtbl_school_dates sd
on a.school_dates_key = sd.school_dates_key
inner join k12intel_dw.dtbl_students s
on a.student_key = s.student_key
inner join k12intel_dw.dtbl_schools sc
on sc.school_key = s.school_key
where 1=1
and sd.rolling_local_school_yr_number = 0
and a.attendance_type in ('LA','LP','LF')
and sc.school_code= ?
and s.student_current_grade_level = ?
group by s.student_id) e
on e.student_id = a.student_id
</sql-query>
</hibernate-mapping>
Questo è il mio dao:
@Repository
public class K12DaoImpl implements K12DaoManager{
@PersistenceContext
private EntityManager em;
// @Autowired
// private SessionFactory sessionFactory;
//
// public void setSessionFactory(SessionFactory sessionFactory) {
// this.sessionFactory = sessionFactory;
// }
@Override
@Transactional(readOnly = true)
public List<AttendanceBreakDown> getAttendanceBreakDownBySchoolAndGP(int school, String gradingPeriod, String gradeLevel) {
Object values[] = new Object[]{new Integer(school), gradingPeriod, gradeLevel,
new Integer(school), gradingPeriod, gradeLevel,
new Integer(school), gradingPeriod, gradeLevel,
new Integer(school), gradingPeriod, gradeLevel,
new Integer(school), gradeLevel
};
// Call Named Query through JPA
// Query query = em.createNamedQuery("attendanceDetailsBySchoolAndGradingPeriod");
//
// for (int i = 0; i < values.length; i++) {
// query.setParameter(i, values[i]);
// }
//
// List<AttendanceBreakDown> list = query.getResultList();
//
// Call Named Query through Hibernate's SessionFactory
// org.hibernate.Query query = sessionFactory.getCurrentSession().getNamedQuery("attendanceDetailsBySchoolAndGradingPeriod");
//
// for (int i = 0; i < values.length; i++) {
// query.setParameter(i, values[i]);
// }
//
// List<AttendanceBreakDown> list = query.list();
//Call Named Query through HibernateTemplate
//List<AttendanceBreakDown> list = getHibernateTemplate().findByNamedQuery("attendanceDetailsBySchoolAndGradingPeriod", values);
//return list;
return null;
}
}
Prima, senza usare Persistence.xml avevo le tipiche impostazioni di hibernate.cfg.xml all'interno di una fabbrica di sessioni di applicationContext con IT, la fabbrica di sessione legata alla dati dati ecc. E tutto funziona bene.
Ora ho persistenza.xml, niente più sessionFactory, EntityManager ora.
Come posso caricare i file HBM.XML ed eseguirli tramite Hibernate anziché tramite JPA 2.0?
Se vedi il codice commentato nel DAO se stavo usando una configurazione di ibernazione che chiamava la query denominata tramite HibernateTeMPlate (che estendeva HibernaDAosupport) funzionava. Come sarebbe il codice adesso?
Grazie
Soluzione
Ho trovato la risposta alla mia domanda. Per farlo funzionare questo è quello che ho fatto:
Uso u003Cmapping-file>... hbm.xmlu003C/mapping-file> dentro u003Cpersistence-unit> in persistenza.xml. Non avevo davvero l'uso del u003Cmapping-file>... hbm.xmlu003C/mapping-file> Tag perché questo mi stava dando ogni sorta di eccezioni, una di queste era DuplicateMapping Exception. Secondo i documenti ho anche pensato di dover usare quel tag, ma si scopre che non è necessario.Creato Edu/KDC/Visioncards/Pojo/AttendceBreakdown.hbm.xml sotto SRC/Main/Risorse
Finalmente nel mio Dao, Ho come segue:
@Override @Transactional(readOnly = true) public List<AttendanceBreakDown> getAttendanceBreakDownBySchoolAndGP(int school, String gradingPeriod, String gradeLevel) { Object values[] = new Object[]{new Integer(school), gradingPeriod, gradeLevel, new Integer(school), gradingPeriod, gradeLevel, new Integer(school), gradingPeriod, gradeLevel, new Integer(school), gradingPeriod, gradeLevel, new Integer(school), gradeLevel }; org.hibernate.Session session = (Session) em.getDelegate(); org.hibernate.Query query = session.getNamedQuery("attendanceDetailsBySchoolAndGradingPeriod"); for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } List<AttendanceBreakDown> list = query.list(); return list; }
Ora posso usare JPA 2.0 tramite EntityManager e passare alla sessione di Hibernate per avere accesso a tutte le funzionalità di Hibernate che JPA 2.0 non offre.