为了可读性和可维护性的目的,我尝试将一些长查询(文本方式)外部化到 orm.xml 文件中,但我不断收到映射异常:无法读取 XML。 这就是我所拥有的:
src/main/resources/META-INF 中的persistence.xml
<?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>
<mapping-file>edu/kdc/visioncards/pojo/orm.xml</mapping-file>
<class>edu.kdc.visioncards.pojo.AttendanceBreakDown</class>
<properties>
<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>
src/main/resources/edu/kdc/visioncards/pojo下的orm.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
<package>edu.kdc.visioncards.pojo</package>
<named-native-query name="attendanceDetailsBySchoolAndGradingPeriod"
result-class="edu.kdc.visioncards.pojo.AttendanceBreakDown"
result-set-mapping="attendanceBreakDownResults">
<query>
select
a.student_name as student_name
,a.student_id as student_id
,a.enrollment_status as enrollment_status
,a.attendance_days as attendance_days
,a.Attendance_Level as 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
</query>
</named-native-query>
<sql-result-set-mapping name="attendanceBreakDownResults">
<entity-result entity-class="edu.kdc.visioncards.pojo.AttendanceBreakDown">
<field-result name="studentName" column="student_name"/>
<field-result name="pupilId" column="student_id"/>
<field-result name="enrollmentStatus" column="enrollment_status"/>
<field-result name="attendanceLevel" column="attendance_level"/>
<field-result name="attendanceDays" column="attendance_days"/>
<field-result name="authorizedAbsences" column="auth_abs"/>
<field-result name="unexcusedAbsences" column="unx_abs"/>
<field-result name="excusedAbsences" column="x_abs"/>
<field-result name="tardies" column="tardies"/>
<field-result name="attendancePct" column="att_pct"/>
</entity-result>
</sql-result-set-mapping>
</entity-mappings>
这就是我将 EntityManager 注入我的 DAO 的方式
@Repository
public class K12DaoImpl implements K12DaoManager{
@PersistenceContext
private EntityManager em;
@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
};
Query query = em.createNamedQuery("attendanceDetailsBySchoolAndGradingPeriod");
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
List<AttendanceBreakDown> list = query.getResultList();
return list;
}
}
当我执行mvn clean tomcat:run 时,我得到一个InvalidMappingException: Unable to read XML它似乎在任何地方都找不到orm.xml,因为我看不到映射错误在哪里。
我之前通过使用将查询映射到对象的 hbm 文件并在 hibernate.cfg.xml 中引用了这些 hbm 文件,使用 Hibernate 成功地外部化了查询,但现在我想通过使用 EntityManager 直接使用 JPA 2.0。
在下面为每个评论添加堆栈跟踪(此堆栈跟踪来自使用 XML 文件而不是注释
2011-12-01 14:32:49,387 [Thread-2] ERROR org.hibernate.util.xml.ErrorLogger - Error parsing XML (6) : cvc-elt.1: Cannot find the declaration of element 'entity-mappings'.
2011-12-01 14:32:49,434 [Thread-2] ERROR org.hibernate.util.xml.ErrorLogger - Error parsing XML (2) : cvc-elt.1: Cannot find the declaration of element 'entity-mappings'.
2011-12-01 14:32:49,450 [Thread-2] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'k12DaoImpl': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [C:\stsworkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\visioncards\WEB-INF\classes\META-INF\spring\applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.InvalidMappingException: Unable to read XML
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [C:\stsworkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\visioncards\WEB-INF\classes\META-INF\spring\applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.InvalidMappingException: Unable to read XML
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:529)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:495)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:656)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:629)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:338)
... 21 more
Caused by: org.hibernate.InvalidMappingException: Unable to read XML
at org.hibernate.util.xml.MappingReader.readMappingDocument(MappingReader.java:101)
at org.hibernate.ejb.Ejb3Configuration.addXMLEntities(Ejb3Configuration.java:734)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:601)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 34 more
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'entity-mappings'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1915)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:705)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:626)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3103)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:922)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at org.dom4j.io.SAXReader.read(SAXReader.java:465)
at org.hibernate.util.xml.MappingReader.readMappingDocument(MappingReader.java:75)
... 41 more
另一个更新:尝试做基于注释
所以我已经注释掉了 persistence.xml 中的标签,并在我的 POJO 中创建了以下注释
package edu.kdc.visioncards.pojo;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
@NamedNativeQuery(
name="attendanceDetailsBySchoolAndGradingPeriod",
query="SAME QUERY HERE AS THE ONE IN ORM.XML ABOVE",
resultClass = AttendanceBreakDown.class,
resultSetMapping="attendanceBreakDownResults"
)
@SqlResultSetMapping(
name="attendanceBreakDownResults",
entities=@EntityResult(entityClass=edu.kdc.visioncards.pojo.AttendanceBreakDown.class,
fields={
@FieldResult(name="studentName", column="student_name"),
@FieldResult(name="studentName", column="student_name"),
@FieldResult(name="pupilId", column="student_id"),
@FieldResult(name="enrollmentStatus", column="enrollment_status"),
@FieldResult(name="attendanceLevel", column="attendance_level"),
@FieldResult(name="attendanceDays", column="attendance_days"),
@FieldResult(name="authorizedAbsences", column="auth_abs"),
@FieldResult(name="unexcusedAbsences", column="unx_abs"),
@FieldResult(name="excusedAbsences", column="x_abs"),
@FieldResult(name="tardies", column="tardies"),
@FieldResult(name="attendancePct", column="att_pct")
}
)
)
public class AttendanceBreakDown {
private String studentName;
private String pupilId;
private String enrollmentStatus;
private String attendanceLevel;
private String attendanceDays;
private String authorizedAbsences;
private String unexcusedAbsences;
private String excusedAbsences;
private String tardies;
private String attendancePct;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getPupilId() {
return pupilId;
}
public void setPupilId(String pupilId) {
this.pupilId = pupilId;
}
public String getEnrollmentStatus() {
return enrollmentStatus;
}
public void setEnrollmentStatus(String enrollmentStatus) {
this.enrollmentStatus = enrollmentStatus;
}
public String getAttendanceLevel() {
return attendanceLevel;
}
public void setAttendanceLevel(String attendanceLevel) {
this.attendanceLevel = attendanceLevel;
}
public String getAttendanceDays() {
return attendanceDays;
}
public void setAttendanceDays(String attendanceDays) {
this.attendanceDays = attendanceDays;
}
public String getAuthorizedAbsences() {
return authorizedAbsences;
}
public void setAuthorizedAbsences(String authorizedAbsences) {
this.authorizedAbsences = authorizedAbsences;
}
public String getUnexcusedAbsences() {
return unexcusedAbsences;
}
public void setUnexcusedAbsences(String unexcusedAbsences) {
this.unexcusedAbsences = unexcusedAbsences;
}
public String getExcusedAbsences() {
return excusedAbsences;
}
public void setExcusedAbsences(String excusedAbsences) {
this.excusedAbsences = excusedAbsences;
}
public String getTardies() {
return tardies;
}
public void setTardies(String tardies) {
this.tardies = tardies;
}
public String getAttendancePct() {
return attendancePct;
}
public void setAttendancePct(String attendancePct) {
this.attendancePct = attendancePct;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("AttendanceBreakDown [studentName=").append(studentName)
.append(", pupilId=").append(pupilId)
.append(", enrollmentStatus=").append(enrollmentStatus)
.append(", attendanceLevel=").append(attendanceLevel)
.append(", attendanceDays=").append(attendanceDays)
.append(", authorizedAbsences=").append(authorizedAbsences)
.append(", unexcusedAbsences=").append(unexcusedAbsences)
.append(", excusedAbsences=").append(excusedAbsences)
.append(", tardies=").append(tardies)
.append(", attendancePct=").append(attendancePct).append("]");
return builder.toString();
}
}
使用基于注释的样式,我得到:
Named query not found: attendanceDetailsBySchoolAndGradingPeriod; nested exception is java.lang.IllegalArgumentException: Named query not found: attendanceDetailsBySchoolAndGradingPeriod
使用以下堆栈跟踪:
org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:286)
org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:15)
edu.kdc.visioncards.dao.K12DaoImpl.getAttendanceBreakDownBySchoolAndGP(K12DaoImpl.java:32)
edu.kdc.visioncards.service.K12ManagerImpl.getAttendanceBreakDownBySchoolAndGradingPeriod(K12ManagerImpl.java:22)
edu.kdc.visioncards.web.PrimerController.test(PrimerController.java:34)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)