【问题标题】:org.hibernate.QueryException: duplicate association path for @ManyToOne Criteriaorg.hibernate.QueryException:@ManyToOne Criteria 的重复关联路径
【发布时间】:2013-01-31 12:16:09
【问题描述】:

我有两个类,它们之间有关系。这些是

com.edfx.adb.persist.Activity:

package com.edfx.adb.persist.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.NaturalId;

@javax.persistence.Entity
@Table(name = "ACTIVITY")
public class Activity extends Entity {

    @Transient
    private static final long serialVersionUID = 4741665931936809028L;

    private String activityId;
    private String activityName;
    private String activityDescription;
    private Customer customer;
    private ActivityType activityType;
    private boolean active;
    private Double mandays;
    private Double price;
    private String manager;
    private List<Participation> participations;

    public Activity() {
        super();
    }

    @NaturalId
    @Column(name = "ACTIVITY_ID", nullable = false)
    public String getActivityId() {
        return activityId;
    }

    public void setActivityId(String activityId) {
        this.activityId = activityId;
    }

    @Lob
    @Column(name = "ACTIVITY_NAME", nullable = false)
    public String getActivityName() {
        return activityName;
    }

    public void setActivityName(String activityName) {
        this.activityName = activityName;
    }

    @Lob
    @Column(name = "ACTIVITY_DESCRIPTION", nullable = false)
    public String getActivityDescription() {
        return activityDescription;
    }

    public void setActivityDescription(String activityDescription) {
        this.activityDescription = activityDescription;
    }

    @ManyToOne
    @JoinColumn(name = "CUSTOMER_ID", nullable = false)
    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    @ManyToOne
    @JoinColumn(name = "ACTIVITY_TYPE_ID", nullable = false)
    public ActivityType getActivityType() {
        return activityType;
    }

    public void setActivityType(ActivityType activityType) {
        this.activityType = activityType;
    }

    @Column(name = "ACTIVE", nullable = false)
    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    @Column(name = "MANDAYS")
    public Double getMandays() {
        return mandays;
    }

    public void setMandays(Double mandays) {
        this.mandays = mandays;
    }

    @Column(name = "PRICE")
    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Column(name = "CUSTOMER_SIDE_MANAGER")
    public String getManager() {
        return manager;
    }

    public void setManager(String manager) {
        this.manager = manager;
    }

    @OneToMany(mappedBy = "activity", fetch = FetchType.LAZY)
    @Cascade(CascadeType.SAVE_UPDATE)
    public List<Participation> getParticipations() {
        return participations;
    }

    public void setParticipations(List<Participation> participations) {
        this.participations = participations;
    }
}

com.edfx.adb.persist.ActivityType:

package com.edfx.adb.persist.entity;

import javax.persistence.Column;
import javax.persistence.Table;
import javax.persistence.Transient;

@javax.persistence.Entity
@Table(name = "ACTIVITY_TYPE")
public class ActivityType extends Entity {

    @Transient
    private static final long serialVersionUID = 2322745769010162801L;

    private String parent;
    private String name;
    private String activityId;

    public ActivityType() {

    }

    @Column(name = "PARENT", nullable = false)
    public String getParent() {
        return parent;
    }

    public void setParent(String parent) {
        this.parent = parent;
    }

    @Column(name = "NAME", nullable = false)
    public String getName() {
        return name;
    }

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

    @Column(name = "ACTIVITY_ID", nullable = false)
    public String getActivityId() {
        return activityId;
    }

    public void setActivityId(String activityId) {
        this.activityId = activityId;
    }
}

它们都扩展了com.edfx.adb.persist.entity.Entity

package com.edfx.adb.persist.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.hibernate.proxy.HibernateProxyHelper;

@MappedSuperclass
public class Entity implements Serializable {

    @Transient
    private static final long serialVersionUID = 7470288121057059283L;

    private Long id;
    private Date createTimestamp;
    private Date lastUpdateTimestamp;
    private Long version;

    public Entity() {
        super();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", updatable = false, nullable = false, unique = true)
    public Long getId() {
        return id;
    }

    @SuppressWarnings("unused")
    private void setId(Long id) {
        this.id = id;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATE_TIMESTAMP")
    public Date getCreateTimestamp() {
        return createTimestamp;
    }

    public void setCreateTimestamp(Date createTimestamp) {
        this.createTimestamp = createTimestamp;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "LAST_UPDATE_TIMESTAMP")
    public Date getLastUpdateTimestamp() {
        return lastUpdateTimestamp;
    }

    public void setLastUpdateTimestamp(Date lastUpdateTimestamp) {
        this.lastUpdateTimestamp = lastUpdateTimestamp;
    }

    @Version
    @Column(name = "VERSION")
    public Long getVersion() {
        return version;
    }

    @SuppressWarnings("unused")
    private void setVersion(Long version) {
        this.version = version;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        return prime * result + ((getId() == null) ? super.hashCode() : getId().hashCode());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (!getClass().equals(HibernateProxyHelper.getClassWithoutInitializingProxy(obj))) {
            return false;
        }

        final Entity other = (Entity) obj;

        if (getId() != other.getId()) {
            if (getId() == null) {
                return false;
            }
            if (!getId().equals(other.getId())) {
                return false;
            }
        }

        return true;
    }
}

现在我正在使用 Primefaces 数据表来显示一个 List&lt;Activity&gt;,其中我对 ActivityType 的字段 name 进行了过滤。 ActivityType 通过@ManyToOne 关系与Activity 相关联。

为了过滤我正在使用的List&lt;Activity&gt;

Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Activity.class);
criteria.createCriteria("activityType").add(Restrictions.like("name", value.toString(), MatchMode.START));

我得到:

null: org.hibernate.QueryException: duplicate association path: activityType
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.createAssociationPathCriteriaMap(CriteriaQueryTranslator.java:172) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.<init>(CriteriaQueryTranslator.java:111) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
    at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:84) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1602) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374) [hibernate-core-4.1.8.Final.jar:4.1.8.Final]
    at com.edfx.adb.dao.ActivityDao.loadActivities(ActivityDao.java:54) [classes:]
    at com.edfx.adb.service.ActivityService.loadActivities(ActivityService.java:101) [classes:]

此错误并非总是显示,也不会在第一次加载后显示。在过滤表格 5-6 次后,我遇到了这个错误。

我担心映射和标准是否正确。任何建议都会非常有帮助。

【问题讨论】:

  • 查看here 一种使用SqlRestrictionexists 的解决方法。

标签: java hibernate-mapping hibernate-criteria hibernate-annotations hibernate-4.x


【解决方案1】:

我认为你需要提供一个别名,所以你应该这样改变你的代码:

Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Activity.class);

criteria.createCriteria("activityType", "at")
   .add(
       Restrictions.like("at.name", value.toString(), MatchMode.START));

【讨论】:

  • 谢谢。当我执行criteria.add(Restrictions.like("activityType.name", value.toString(), MatchMode.ANYWHERE)); 时出现错误null: org.hibernate.QueryException: could not resolve property: activityType.name of: com.edfx.adb.persist.entity.Activity
  • 尝试为activityType 创建一个别名,正如我在答案中编辑的那样
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多