由于我的数据库的复杂性,我决定创建一个新对象,在其中仅指定我将使用的参数。为了进行自定义查询,我在 JPA 中使用 createNativeQuery。跟随我的目标。
POJO:
@Entity
public class Unidade implements Serializable{
private static final long serialVersionUID = 1L;
private Long numeroUnidade;
private String nomeUnidade;
private Integer numeroCep;
private Integer numeroCepComplemento;
private String tipoServico;
private Integer status;
private String logradouro;
private String bairro;
private String cidade;
private String uf;
private Integer statusVinculo;
//getter and setters
目前我正在使用以下选择来返回简单整数并且可以正常工作而不会出现任何问题。
@PersistenceContext(unitName="projetoAtividade")
private EntityManager em;
public void selectTeste(){
int quantidade = (Integer) em.createNativeQuery("select count(*) from abc.nattbu29_escritorio;").getSingleResult();
System.out.println("========== QUANTIDADE DE REGISTRO NA TABELA ===========");
System.out.println(quantidade);
}
虽然前面的查询工作正常,但是当提交一个复杂的查询并放置相应的别名时,使用createNativeQuery并放置对象返回,hibernate会抛出异常(org.hibernate.MappingException:未知)。
记住我创建了一个新类并指定了@Entity。
查询:
@SuppressWarnings("unchecked")
public List<UnidadeTeste> buscarUnidadeGenerica(int numeroCeps, int numeroComplementoCeps){
List<UnidadeTeste> lsita = new ArrayList<UnidadeTeste>();
String query = "SELECT "
+"TBZ21.NATURAL as numeroPv, "
+"TBZ21.UNIDADE as nomePv, "
+"TBZ21.SITUACAO as statusVinculacao, "
+"TBJ55.TPO_ATUACAO_U44 as tipoServAZW, "
+"TBJ55.SITUACAO_ATUAL as status, "
+"TBH18.LOCALIDADE as cidade, "
+"'' as bairro, "
+"'' as logradouro, "
+"TBH18.CEP as numeroCep, "
+"TBH18.CEP_COMPLEMENTO as numeroCepComplemento, "
+"TBH18.FK_AZWVWL22_UNISG as uf "
+"FROM AZW.AZWTBJ55_RGATUACAO TBJ55 "
+"LEFT JOIN AZW.AZWTBH18_LOCALIDADE TBH18 ON "
+"TBH18.LOCALIDADEE = TBJ55.LOCALIDADEE "
+"LEFT JOIN AZW.AZWTBZ21_UNIDADE TBZ21 ON "
+"TBJ55.NATURAL = TBZ21.NATURAL "
+"WHERE TBH18.CEP = ?1 "
+"AND TBH18.CEP_COMPLEMENTO = ?2; "
lsita = em.createNativeQuery(query, Unidade.class)
.setParameter(1, numeroCeps)
.setParameter(2, numeroComplementoCeps)
.getResultList();
System.out.println(lsita.size()+"<<<<=====================");
return lsita;
}
错误:
Caused by: org.hibernate.MappingException: Unknown entity: br.com.project.modelo.UnidadeTeste
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1031) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.getSQLLoadable(SQLQueryReturnProcessor.java:336) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processRootReturn(SQLQueryReturnProcessor.java:377) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processReturn(SQLQueryReturnProcessor.java:356) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.process(SQLQueryReturnProcessor.java:172) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.loader.custom.sql.SQLCustomQuery.<init>(SQLCustomQuery.java:87) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.query.spi.NativeSQLQueryPlan.<init>(NativeSQLQueryPlan.java:67) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:155) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.internal.AbstractSessionImpl.getNativeSQLQueryPlan(AbstractSessionImpl.java:218) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:224) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:156) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:252) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
... 84 more
在我通过互联网搜索时,几乎所有论坛主题的解决方案答案都是一致的:“将@Entity放在类声明之前”,但是,这对我不起作用。
我“花了”一整天的时间试图寻找有效的解决方案,但不幸的是, 我没有取得成功。有人可以说一个新的方法来解决我的问题吗? 我在两个不同的项目中进行了测试,并发生了同样的问题。
问题补充:
各位,我尝试在我的类中创建一个@SqlResultSetMapping,编码如下,但现在,休眠会引发另一个异常:
ERROR [org.jboss.ejb3.invocation] (http--127.0.0.1-8888-2) JBAS014134: EJB Invocation failed on component AtividadeEJB for method public void br.com.project.jboss.modelo.AtividadeEJB.testeChamada(): javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.MappingException: Unknown SqlResultSetMapping [UnidadeResult]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:166) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:230) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:304) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
我的新 POJO:
@Entity
@SqlResultSetMapping(name="UnidadeResult",
entities={
@EntityResult(entityClass=UnidadeTeste.class, fields={
@FieldResult(name="tx_descricao", column="nomePv"),
@FieldResult(name="nu_idntr_pessoa", column="id")})},
columns={
@ColumnResult(name="nomePv")}
)
public class UnidadeTeste implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private String nomePv;
public String getNomePv() {
return nomePv;
}
public void setNomePv(String nomePv) {
this.nomePv = nomePv;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
我的EJB:
@SuppressWarnings("unchecked")
public void testeChamada(){
List<Object> lista = em.createNativeQuery("SELECT nu_idntr_pessoa as id, email as nomePv FROM pessoa;", "UnidadeResult").getResultList();
System.out.println("===============>>"+lista.size());
}
如果您想将本机查询的结果返回到对象,我建议使用 SqlResultSetMapping。
否则,请将返回类型设置为:
List<Object[]> results = em.createNativeQuery(query)
.setParameter(1, numeroCeps)
.setParameter(2, numeroComplementoCeps)
.getResultList();
然后循环遍历结果列表,并将 Object 数组的每个成员转换为其数据类型。
List<UnidadeTeste> lsita = new ArrayList<UnidadeTeste>();
lsita = em.createNativeQuery(query, Unidade.class)
这里存在类型不匹配。例外情况很明显:未知实体:br.com.project.modelo.UnidadeTeste
您的实体是 Unidade,因此您必须返回
List<Unidade>
而不是 UnidadeTeste
。
我的解决方案是:
在本主题中:当我的项目中没有任何实体时,如何将本机查询映射到 POJO? 准确描述了我的问题。但即使之前读过,我也无法理解一点细节,这解决了我的问题。
即使为接收查询结果创建一个简单的实体,也有必要将我的类映射到 persistence.xml 中。这是我的错误!
所以,我现在的项目:
持久性.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="projetoAtividade" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/projetoAtividade</jta-data-source>
//another classes
<class>br.com.project.modelo.UnidadeTeste</class>
//properties of connection
UnidadeTeste.class:
package br.com.project.modelo;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class UnidadeTeste {
@Id
private Long id;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
EJB:
@SuppressWarnings("unchecked")
public void testeChamada(){
List<UnidadeTeste> lista = em.createNativeQuery("SELECT nu_idntr_pessoa AS id, email AS description FROM Pessoa", UnidadeTeste.class).getResultList();
System.out.println("===============>>"+lista.size());
}
请记住,您需要在类中创建的属性上为同名的列添加别名。
您还应该定义一个 SqlResultSetMapping 注释并在命名的本机查询注释中引用它:
@SqlResultSetMapping(
name = "nameToReferTO",
classes = @ConstructorResult(targetClass = X.class,
columns = {@ColumnResult(name = "A"), @ColumnResult(name = "B")})
)