我正在開發一個應用程序來幫助我的辦公室跟蹤和管理評論。在應用程序中,我將Hibernate 3.6.3的JPA 2.0作爲我的底層提供者。我也使用spring將持久化上下文注入到我的DAO中。我已經建立了這樣一個域,使得有一個評論,一個參與者和一個角色實體。實體管理器返回@OneToMany相關實體的重複副本
我遇到的問題是,如果參與者具有多個角色,當我從實體經理獲得審閱時,參與者列表中存在相同參與者(即相同ID)的重複副本。我還發現重複次數與數量角色直接相關(即,如果參與者有3個角色,則參與者在評論參與者列表中出現3次)
我以前使用過直接Hibernate,但這是我第一次使用JPA,所以我確定我配置了錯誤的東西。我只是不知道它是什麼。
下面是代碼:
評論:
@Entity
public class Review extends BaseModel{
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER, optional=false)
private Item item;
@Column(name="ISNEW", nullable=false)
private boolean isNew;
@Enumerated(EnumType.STRING)
@Column(name="STATUS", nullable=false)
private ReviewStatus status;
@Enumerated(EnumType.STRING)
@Column(name="PHASE", nullable=false)
private Phase phase;
@Enumerated(EnumType.STRING)
@Column(name="REVIEW_TYPE", nullable=false)
private ReviewType reviewType;
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private List<Participant> participants;
@OneToMany(cascade=CascadeType.ALL)
private List<Defect> defects;
@Column(name="START_DATE", nullable=false)
private Date startDate;
@Column(name="MEETING_DATE", nullable=false)
private Date meetingDate;
@Column(name="FINISH_DATE")
private Date finishDate;
@Column(name="DURATION", nullable=false)
private Double duration;
public Item getItem()
{
return item;
}
public void setItem(Item item)
{
this.item = item;
}
public List<Participant> getParticipants() {
return participants;
}
public void setParticipants(List<Participant> participants) {
this.participants = participants;
}
public List<Defect> getDefects() {
return defects;
}
public void setDefects(List<Defect> defects) {
this.defects = defects;
}
public boolean isNew() {
return isNew;
}
public void setNew(boolean isNew) {
this.isNew = isNew;
}
public Phase getPhase() {
return phase;
}
public void setPhase(Phase phase) {
this.phase = phase;
}
public Double getDuration() {
return duration;
}
public void setDuration(Double duration) {
this.duration = duration;
}
public ReviewStatus getStatus() {
return status;
}
public void setStatus(ReviewStatus status) {
this.status = status;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getMeetingDate() {
return meetingDate;
}
public void setMeetingDate(Date meetingDate) {
this.meetingDate = meetingDate;
}
public Date getFinishDate() {
return finishDate;
}
public void setFinishDate(Date finishDate) {
this.finishDate = finishDate;
}
public ReviewType getReviewType()
{
return reviewType;
}
public void setReviewType(ReviewType reviewType)
{
this.reviewType = reviewType;
}
}
參與者:
@Entity
public class Participant extends BaseModel{
private Double inspectionTime;
@ManyToOne(cascade=CascadeType.ALL, optional=false)
private Person person;
@ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Role> roles;
public Double getInspectionTime() {
return inspectionTime;
}
public void setInspectionTime(Double preInspectionTime) {
this.inspectionTime = preInspectionTime;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
角色:
@Entity
public class Role extends BaseModel{
@Column(nullable=false, unique=true)
private String name;
private String responsiblity;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResponsiblity() {
return responsiblity;
}
public void setResponsiblity(String responsiblity) {
this.responsiblity = responsiblity;
}
}
基地:
@MappedSuperclass
public abstract class BaseModel {
@Id
@GeneratedValue
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
DataAccessObject它使用了EntityManager:
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public class ReviewDaoJpaImpl implements ReviewDao
{
@PersistenceContext
private EntityManager em;
public Review getReviewById(Long id)
{
return em.find(Review.class, id);
}
}
呼叫接收重複:
Review review = reviewDao.getReviewById(1776L);
List<Participant> participants = review.getParticipants();
for (Participant participant : participants)
{
System.out.println(participant.getPerson().getName());
}
就是這樣。我很尷尬N + 1沒有出現在我對這個問題的任何搜索中。我想我沒有使用正確的關鍵字。謝謝你的幫助。我知道我做錯了什麼。 – Scott 2011-04-21 21:21:43
你能解釋更多關於N + 1嗎? – Dejell 2013-06-20 22:01:39
@Odelya Google for「n + 1 hibernate中的問題」第一擊是:http://stackoverflow.com/questions/97197/what-is-the-n1-selects-issue – Ralph 2013-06-21 12:37:01