@ManyToOne加入FetchMode生成内部联接

问题描述:

阅读所有文档,在@ManyToOne上使用@Fetch(FetchMode.JOIN)默认情况下,我相信会生成一个左外部联接,但对我而言,它始终生成一个内部联接。这是我的豆子:@ManyToOne加入FetchMode生成内部联接

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

/** 
* PensionMember entity. @author MyEclipse Persistence Tools 
*/ 
@Entity 
@Table(name = "Z_PENSION_MEMBERS", schema = "DANAOS") 
public class PensionMember implements java.io.Serializable { 

    private static final long serialVersionUID = -4541446336298304689L; 

    // Fields 

    private Long id; 
    private Long personsCode; 
    private String employeeCode; 
    private String personType; 
    private CrewOfficeEmployee employee; 
    private PersonTO person; 

    // Property accessors 
    @Id 
    @Column(name = "ID", unique = true, nullable = false, precision = 0) 
    public Long getId() { 
     return this.id; 
    } 

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

    @Column(name = "EMPLOYEE_CODE", length = 12) 
    public String getEmployeeCode() { 
     return this.employeeCode; 
    } 

    public void setEmployeeCode(String employeeCode) { 
     this.employeeCode = employeeCode; 
    } 

    @ManyToOne(cascade = CascadeType.REFRESH, optional=true) 
    @JoinColumn(name = "EMPLOYEE_CODE", insertable = false, updatable = false) 
    @Fetch(FetchMode.JOIN) 
    public CrewOfficeEmployee getEmployee(){ 
     return employee; 
    } 

    public void setEmployee(CrewOfficeEmployee employee){ 
     this.employee = employee; 
    } 

    @Column(name = "PERSONS_CODE", precision = 126, scale = 0, insertable = false, updatable = false) 
    public Long getPersonsCode() { 
     return this.personsCode; 
    } 

    public void setPersonsCode(Long personsCode) { 
     this.personsCode = personsCode; 
    } 

    @ManyToOne(cascade = CascadeType.REFRESH, optional=true) 
    @JoinColumn(name = "PERSONS_CODE") 
    @Fetch(FetchMode.JOIN) 
    public PersonTO getPerson() { 
     return person; 
    } 

    public void setPerson(PersonTO person) { 
     this.person = person; 
    } 

    @Column(name = "PERSON_TYPE", nullable = false, length = 1) 
    public String getPersonType() { 
     return this.personType; 
    } 

    public void setPersonType(String personType) { 
     this.personType = personType; 
    } 
} 

import java.util.Date; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

/** 
* CrewOfficeEmployee entity. @author MyEclipse Persistence Tools 
*/ 
@Entity 
@Table(name = "Z_CREW_OFFICE_EMPLOYEES", schema = "DANAOS") 
public class CrewOfficeEmployee implements java.io.Serializable { 

    private static final long serialVersionUID = -5900130959401376537L; 

    // Fields 

    private String id; 
    private Integer crewOfficeJobTitleId; 
    private String name; 
    private String surname; 
    private Date dateOfBirth; 
    private Date effectiveJoiningDate; 
    private Date joiningDate; 
    private Date leavingDate; 

    // Property accessors 
    @Id 
    @Column(name = "ID", unique = true, nullable = false, length = 12) 
    public String getId() { 
     return this.id; 
    } 

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

    @Column(name = "JOB_TITLE_ID", nullable = false) 
    public Integer getCrewOfficeJobTitleId() { 
     return crewOfficeJobTitleId; 
    } 

    public void setCrewOfficeJobTitleId(Integer crewOfficeJobTitleId) { 
     this.crewOfficeJobTitleId = crewOfficeJobTitleId; 
    } 

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

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

    @Column(name = "SURNAME", nullable = false, length = 30) 
    public String getSurname() { 
     return this.surname; 
    } 

    public void setSurname(String surname) { 
     this.surname = surname; 
    } 

    @Column(name = "DATE_OF_BIRTH", nullable = false, length = 7) 
    public Date getDateOfBirth() { 
     return this.dateOfBirth; 
    } 

    public void setDateOfBirth(Date dateOfBirth) { 
     this.dateOfBirth = dateOfBirth; 
    } 

    @Column(name = "EFFECTIVE_JOINING_DATE", nullable = false, length = 7) 
    public Date getEffectiveJoiningDate() { 
     return this.effectiveJoiningDate; 
    } 

    public void setEffectiveJoiningDate(Date effectiveJoiningDate) { 
     this.effectiveJoiningDate = effectiveJoiningDate; 
    } 

    @Column(name = "JOINING_DATE", nullable = false, length = 7) 
    public Date getJoiningDate() { 
     return this.joiningDate; 
    } 

    public void setJoiningDate(Date joiningDate) { 
     this.joiningDate = joiningDate; 
    } 

    @Column(name = "LEAVING_DATE", length = 7) 
    public Date getLeavingDate() { 
     return this.leavingDate; 
    } 

    public void setLeavingDate(Date leavingDate) { 
     this.leavingDate = leavingDate; 
    } 
} 

这是我的查询:

Criteria crit = getSession().createCriteria(PensionMember.class); 
crit.createAlias("employee", "employee"); 
crit.createAlias("person", "person"); 
crit.add(
    Restrictions.or(
     Restrictions.and(
      Restrictions.eq(PERSON_TYPE, "V"), 
      Restrictions.like("person.personsSurname", surname, MatchMode.START).ignoreCase() 
     ), 
     Restrictions.and(
      Restrictions.eq(PERSON_TYPE, "O"), 
      Restrictions.like("employee.surname", surname, MatchMode.START).ignoreCase() 
     ) 
    ) 
); 

...这是生成的SQL:

select * from (select this_.ID as ID23020_6_, this_.EMPLOYEE_CODE as EMPLOYEE3_23020_6_, this_.PERSONS_CODE as PERSONS7_23020_6_, 
this_.PERSON_TYPE as PERSON6_23020_6_, employee1_.ID as ID23010_0_, employee1_.JOB_TITLE_ID as JOB2_23010_0_, 
employee1_.DATE_OF_BIRTH as DATE3_23010_0_, employee1_.EFFECTIVE_JOINING_DATE as EFFECTIVE4_23010_0_, 
employee1_.JOINING_DATE as JOINING5_23010_0_, employee1_.LEAVING_DATE as LEAVING6_23010_0_, 
employee1_.NAME as NAME23010_0_, employee1_.SURNAME as SURNAME23010_0_, person2_.STATUS_CODE as STATUS2_22758_1_, etc 
from DANAOS.Z_PENSION_MEMBERS this_ 
inner join DANAOS.Z_CREW_OFFICE_EMPLOYEES employee1_ on this_.EMPLOYEE_CODE=employee1_.ID 
inner join PERSONS person2_ on this_.PERSONS_CODE=person2_.PERSONS_CODE 
where ((this_.PERSON_TYPE=? and lower(person2_.PERSONS_SURNAME) like ?) or 
(this_.PERSON_TYPE=? and lower(employee1_.SURNAME) like ?))) where rownum <= ? 

怎么来的?有人能告诉我我做错了什么吗?

感谢, 尼尔

我使用Hibernate的3.6.10顺便说一句

+0

你能提供您Z_PENSION_MEMBERS表的DDL? –

@ManyToOne(cascade = CascadeType.REFRESH, optional=true) 
@JoinColumn(name = "EMPLOYEE_CODE", insertable = false, updatable = false) 
@Fetch(FetchMode.JOIN)  
public CrewOfficeEmployee getEmployee(){ 
    return employee; 
} 

首先改变的 “插入=假” 为true。

我得到(左外连接):

休眠:

选择this_.ID为ID1_1_1_,this_.EMPLOYEE_CODE1为EMPLOYEE3_1_1_, this_.EMPLOYEE_CODE为EMPLOYEE2_1_1_,crewoffice2_.ID为ID1_0_0_ , crewoffice2_.JOB_TITLE_ID如JOB_TITL2_0_0_, crewoffice2_.DATE_OF_BIRTH如DATE_OF_3_0_0_, crewoffice2_.EFFECTIVE_JOINING_DATE如EFFECTIV4_0_0_, crewoffice2_.JOINING_DATE如JOINING_5_0_0_,crewoffice2_.LEAVING_DATE 为LEAVING_6_0_0_,crewoffice2_.NAME为NAME7_0_0_, crewoffice2_.SURNAME作为SURNAME8_0_0_从Z_PENSION_MEMBERS THIS_ 左外连接由this_.ID ASC Z_CREW_OFFICE_EMPLOYEES上 this_.EMPLOYEE_CODE1 = crewoffice2_.ID为了crewoffice2_

我觉得你的代码应该管用。

+0

感谢您的回复。这让我意识到,这是问题而不是映射的问题。 findById()提供了一个外连接,但是我正在运行的查询(请参阅编辑的问题)仍然会创建一个内连接 –

已经意识到这是标准的查询,这是问题,解决的办法是改变createAlias()方法:

Criteria crit = getSession().createCriteria(PensionMember.class); 
crit.createAlias("employee", "employee", CriteriaSpecification.LEFT_JOIN); 
crit.createAlias("person", "person", CriteriaSpecification.LEFT_JOIN);