2012-03-09 64 views
2

我是JPA的新手,我花了最近4天的时间试图弄清楚为什么* & ^!@我的查询不断爆炸。看起来问题似乎与我正在使用的变量的名称有关。请参阅下面的我的实体和测试课程。我很抱歉,但我尽量简化它。与实体变量名称相关的JPA/Hibernate查询失败

@Entity 
public class MyEntity { 
@Id 
@GeneratedValue(strategy = GenerationType.SEQUENCE) 
private long id; 
@Column(length = 50) 
private String name; 
@ManyToOne 
private MyEntity myEntity; 
@OneToMany(cascade = CascadeType.ALL, mappedBy = "myEnt", fetch = FetchType.EAGER) 
@MapKey(name = "typeName") 
private Map<String, ContainedEntity> ecConfigs; 

public MyEntity() { 
} 

public MyEntity(String name, MyEntity myEntity) { 
    this.name = name; 
    this.myEntity = myEntity; 
} 

public MyEntity(String name) { 
    this.name = name; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public long getId() { 
    return id; 
} 

public void setId(long id) { 
    this.id = id; 
} 

public Map<String, ContainedEntity> getEcConfigs() { 
    return ecConfigs; 
} 

public void setEcConfigs(Map<String, ContainedEntity> ecConfigs) { 
    this.ecConfigs = ecConfigs; 
} 

public MyEntity getMyEntity() { 
    return myEntity; 
} 

public void setMyEntity(MyEntity myEntity) { 
    this.myEntity = myEntity; 
} 

public String toString() { 
    return name + " -- " + myEntity; 
} 
} 
@IdClass(ContainedEntityPK.class) 
@Entity 
public class ContainedEntity { 

@Id 
private String typeName; 
@Id 
private MyEntity myEnt; 
@Column(length = 255) 
private String ceName; 

public ContainedEntity() { 
} 

public ContainedEntity(String typeName, String ceName) { 
    super(); 
    this.typeName = typeName; 
    this.ceName = ceName; 
} 

public String getTypeName() { 
    return typeName; 
} 

public void setTypeName(String typeName) { 
    this.typeName = typeName; 
} 

public MyEntity getMyEnt() { 
    return myEnt; 
} 

public void setMyEnt(MyEntity myEnt) { 
    this.myEnt = myEnt; 
} 

public String getCeName() { 
    return ceName; 
} 

public void setCeName(String ceName) { 
    this.ceName = ceName; 
} 

} 
public class ContainedEntityPK implements Serializable{ 
private static final long serialVersionUID = -1714218588564578557L; 
@Column(length = 255) 
private String typeName; 
@ManyToOne 
private MyEntity myEnt; 

public ContainedEntityPK() { 
} 

public ContainedEntityPK(String typeName, MyEntity myEnt) { 
    super(); 
    this.typeName = typeName; 
    this.myEnt = myEnt; 
} 

public String getTypeName() { 
    return typeName; 
} 

public void setTypeName(String name) { 
    this.typeName = name; 
} 

public MyEntity getMyEnt() { 
    return myEnt; 
} 

public void setMyEnt(MyEntity myEnt) { 
    this.myEnt = myEnt; 
} 

public int hashCode() { 
    return (int) (typeName.hashCode() + myEnt.hashCode()); 
} 

public boolean equals(Object obj) { 
    if (obj == null) 
     return false; 
    if (obj == this) 
     return true; 
    if (!(obj instanceof ContainedEntityPK)) 
     return false; 
    ContainedEntityPK pk = (ContainedEntityPK) obj; 
    return pk.getMyEnt().equals(myEnt) && pk.typeName.equals(typeName); 
} 
} 
public class Tester { 
static EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPersistenceUnit"); 

/** 
* @param args 
*/ 
public static void main(String[] args) { 
    addEntities(); 
    findEntity("aEntity"); 
    findEntity("bEntity"); 
} 

public static void addEntities() { 
    EntityManager em = emf.createEntityManager(); 

    MyEntity aEntity = new MyEntity("aEntity"); 
    MyEntity bEntity = new MyEntity("bEntity", aEntity); 

    em.getTransaction().begin(); 
    em.persist(aEntity); 
    em.persist(bEntity); 
    em.getTransaction().commit(); 
    em.close(); 
} 

public static void findEntity(String name) { 
    EntityManager em = emf.createEntityManager(); 

    TypedQuery<MyEntity> q = em.createQuery("SELECT M FROM MyEntity M WHERE M.name=:name", MyEntity.class); 
    q.setParameter("name", name); 
    System.out.println(q.getSingleResult()); 
} 
} 
<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> 
<persistence-unit name="testPersistenceUnit" transaction-type="RESOURCE_LOCAL"> 
<provider>org.hibernate.ejb.HibernatePersistence</provider> 
<class>test.nocommit.MyEntity</class> 
<class>test.nocommit.ContainedEntity</class> 
<properties> 
    <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/> 
    <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@server:1521:instance"/> 
    <property name="javax.persistence.jdbc.user" value="user"/> 
    <property name="javax.persistence.jdbc.password" value="pass"/> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> 
    <property name="hibernate.hbm2ddl.auto" value="create"/> 
</properties> 
</persistence-unit> 
</persistence> 

当我运行先前的主类,它的行为如我所料,并得到下面的输出:
aEntity - 空
bEntity - aEntity - null

但是,如果我更改MyEntity.ecConfigs VA可变结构名称MyEntity.secConfigs和更改getter/setter方法给:

public Map<String, ContainedEntity> getSecConfigs() { 
     return secConfigs; 
    } 

    public void setSecConfigs(Map<String, ContainedEntity> secConfigs) { 
     this.secConfigs = secConfigs; 
    } 

它上的Findentity( “bEntity”)炸毁;呼叫。我的输出是:
aEntity - 空
其次是例外:

Exception in thread "main" org.hibernate.AssertionFailure: null identifier 
    at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:69) 
    at org.hibernate.internal.AbstractSessionImpl.generateEntityKey(AbstractSessionImpl.java:240) 
    at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:722) 
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:635) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:856) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259) 
    at org.hibernate.loader.Loader.loadEntity(Loader.java:2058) 
    at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82) 
    at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72) 
    at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3697) 
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:439) 
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:420) 
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204) 
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:251) 
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148) 
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:954) 
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:903) 
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:610) 
    at org.hibernate.type.EntityType.resolve(EntityType.java:438) 
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:150) 
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1006) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:883) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289) 
    at org.hibernate.loader.Loader.doList(Loader.java:2463) 
    at org.hibernate.loader.Loader.doList(Loader.java:2449) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2279) 
    at org.hibernate.loader.Loader.list(Loader.java:2274) 
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:470) 
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355) 
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:196) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1115) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) 
    at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:280) 
    at test.nocommit.Tester.findEntity(Tester.java:38) 
    at test.nocommit.Tester.main(Tester.java:17) 

起初我在春天责备这一点,但我已经剥夺一切春天的权利,并仍然遇到的问题。

我的休眠版本调用自己4.0.1.Final

我在这里丢失了什么吗?是否有一些变量名称要求?我是否踩了一些保留字?我没有正确地指定某些东西吗?从我所知道的情况来看,可能与自引用实体以及复合主键有一些关系......我目前在我的隔间里感到困惑和哭泣。

+0

在DataNucleus JPA(带有ecConfigs或secConfigs)上正常工作。我在任何地方都看不到保留字,除此之外,如果在RDBMS中有某个保留字,那么它可以很容易地通过JPA实现引用。请注意,您尚未在GeneratedValue中指定序列名称,因此需要添加(可能它简直错过了该帖子,但您确实拥有它)? – DataNucleus 2012-03-10 09:24:54

+0

OP的错误报告:https://hibernate.atlassian.net/浏览/ HHH-7178 – Arjan 2015-01-02 15:43:56

回答

1

JPA的美妙之处在于它是一个规范,而不是实现。你的代码看起来像是针对JPA规范写的,而不是休眠。

我发现EclipseLink有很多更好的描述在它的错误信息,当你搞砸了。我试着用EclipseLink运行你的代码,看看你是否得到了更好的错误信息。

我会一直看着你的代码,直到然后看能不能发现什么是错的......

+0

有趣...我接受了你的建议,而EcliplseLink似乎也有它的牛肉......但完全不同的牛肉。 – Marc 2012-03-12 15:03:07

+0

'异常说明:来自[test.nocommit.ContainedEntityPK]的[test.nocommit.MyEntity]类型的派生复合主键属性[myEnt]应该与[test.nocommit.MyEntity]中的父项ID字段具有相同的类型。也就是说,它应该是[java.lang.Long]类型。' 更好的错误信息。这显然对PK很生气,所以我将myEnt类型改为long,并且它在EclipseLink中工作。那PK中的复杂类型是如何定义的?另外,我用这个pk重新回到了休眠状态,直到我尝试持有一个包含ContainedEntity的MyEntity。 – Marc 2012-03-12 15:15:38

+0

'导致:java.lang.IllegalArgumentException:无法设置长字段test.nocommit.ContainedEntityPK.myEnt test.nocommit.MyEntity' 因此,Hibernate有点喜欢它,直到我使用它,然后它明确doesn'不喜欢它......呃。 附注......看起来我已经和Hibernate结婚了,正如我的领主声明的那样,它与其他产品集保持一致。 – Marc 2012-03-12 15:19:39

0

好吧,这不是一个简单的解决方案,我今天所面临的同样的问题有两个的POJO(A和B)都有一个java.utl.Long字段作为@Id。 A pojo有一个领域是另一个实体的集合。

我类似这样的加载过程:A - >乙 - > BC

加载过程中崩溃,因为C的,加载c的投掷IN/OUT的失踪PARAM,但被隐藏在报告的异常背后。

在我的情况下,我能够解决这个问题,因为从B分离c使用fetchmode'SELECT'而不是'SUBSELECT'。但我放松了8小时搜索信息。我的休眠版本是3.6。10-决赛