我有两个对象,程序和分类,一个程序到多个分类关系。 这是我的标准查询:
Criteria crit2 = sessionFactory.getCurrentSession()
.createCriteria(Program.class)
.add(Restrictions.eq("code", input.getCode()))
.createAlias("classifications", "cl")
.add(Restrictions.eq("cl.id", 3249023L));
List<Program> programs2 = crit2.list();
并且它生成的SQL有一个额外的左外连接,我无法理解?
的目的Hibernate:
select
this_.id as id16_2_,
this_.created as created16_2_,
this_.modified as modified16_2_,
this_.version as version16_2_,
this_.active as active16_2_,
this_.adminProgramId as adminPro6_16_2_,
this_.code as code16_2_,
this_.deletable as deletable16_2_,
this_.desciption as desciption16_2_,
this_.discontinued as discont10_16_2_,
this_.effectiveDate as effecti11_16_2_,
this_.expirationDate as expirat12_16_2_,
this_.name as name16_2_,
this_.programVersion as program14_16_2_,
cl1_.id as id1_0_,
cl1_.created as created1_0_,
cl1_.modified as modified1_0_,
cl1_.version as version1_0_,
cl1_.causeOfLoss as causeOfL5_1_0_,
cl1_.code as code1_0_,
cl1_.description as descript7_1_0_,
cl1_.lobCode as lobCode1_0_,
cl1_.lobName as lobName1_0_,
cl1_.premiumBaseCode as premium10_1_0_,
cl1_.premiumBaseDesc as premium11_1_0_,
cl1_.premiumBaseValue as premium12_1_0_,
cl1_.program_id as program13_1_0_,
program4_.id as id16_1_,
program4_.created as created16_1_,
program4_.modified as modified16_1_,
program4_.version as version16_1_,
program4_.active as active16_1_,
program4_.adminProgramId as adminPro6_16_1_,
program4_.code as code16_1_,
program4_.deletable as deletable16_1_,
program4_.desciption as desciption16_1_,
program4_.discontinued as discont10_16_1_,
program4_.effectiveDate as effecti11_16_1_,
program4_.expirationDate as expirat12_16_1_,
program4_.name as name16_1_,
program4_.programVersion as program14_16_1_
from
Program this_
inner join
Classification cl1_
on this_.id=cl1_.program_id
left outer join
Program program4_
on cl1_.program_id=program4_.id
where
this_.code=?
and cl1_.id=?
有谁知道为什么会有这个区块:
left outer join
Program program4_
on cl1_.program_id=program4_.id
我如何摆脱它,因为额外的连接会影响性能。
我正在使用hibernate 3.6.8
这是Program class:
package com.sg.pds.domain.entity.ratedelivery;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlTransient;
import org.hibernate.annotations.Index;
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Program extends BaseEntity {
private String code;
private String desciption;
private String name;
@XmlElement(name="classification") @XmlElementWrapper(name = "classifications")
private Set<Classification> classifications = new HashSet<Classification>();
@XmlElement(name="debitCredit") @XmlElementWrapper(name = "debitCredits")
private Set<DebitCredit> debitCredits = new HashSet<DebitCredit>();
@XmlElement(name="minPremium") @XmlElementWrapper(name = "minPremiums")
private Set<DebitCredit> minPremiums = new HashSet<DebitCredit>();
@XmlElement(name="deductible") @XmlElementWrapper(name = "deductibles")
private Set<Deductible> deductibles = new HashSet<Deductible>();
@XmlElement(name="optionalCoverage") @XmlElementWrapper(name = "optionalCoverages")
private Set<OptionalCoverage> optionalCoverages = new HashSet<OptionalCoverage>();
@XmlTransient
private Date expirationDate;
@XmlTransient
private Date effectiveDate;
@XmlTransient
private String programVersion;
@XmlTransient
private Boolean discontinued;
@XmlTransient
private Boolean active;
@XmlTransient
private Boolean deletable;
@XmlElement(name="company") @XmlElementWrapper(name = "companies")
private Set<String> companies = new HashSet<String>();
@XmlTransient
private Set<Territory> territories = new HashSet<Territory>();
@XmlTransient
private String adminProgramId; // primary key from program table in admin db
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
public Set<DebitCredit> getMinPremiums() {
return minPremiums;
}
public void setMinPremiums(Set<DebitCredit> minPremiums) {
this.minPremiums = minPremiums;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
@OrderBy("lobCode ASC")
public Set<OptionalCoverage> getOptionalCoverages() {
return optionalCoverages;
}
public void setOptionalCoverages(Set<OptionalCoverage> optionalCoverages) {
this.optionalCoverages = optionalCoverages;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
@OrderBy("lobCode ASC")
public Set<Deductible> getDeductibles() {
return deductibles;
}
public void setDeductibles(Set<Deductible> deductibles) {
this.deductibles = deductibles;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
@OrderBy("name ASC")
public Set<Territory> getTerritories() {
return territories;
}
public void setTerritories(Set<Territory> territories) {
this.territories = territories;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
@OrderBy("name ASC")
public Set<DebitCredit> getDebitCredits() {
return debitCredits;
}
public void setDebitCredits(Set<DebitCredit> debitCredits) {
this.debitCredits = debitCredits;
}
@ElementCollection
@CollectionTable(name="Company", joinColumns=@JoinColumn(name="program_id"))
@Column(name="name", length=255)
public Set<String> getCompanies() {
return companies;
}
public void setCompanies(Set<String> companies) {
this.companies = companies;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="program", fetch=FetchType.LAZY)
@OrderBy("code ASC")
public Set<Classification> getClassifications() {
return classifications;
}
public void setClassifications(Set<Classification> classifications) {
this.classifications = classifications;
}
public String getAdminProgramId() {
return adminProgramId;
}
public void setAdminProgramId(String adminProgramId) {
this.adminProgramId = adminProgramId;
}
@Column(length=255)
public String getProgramVersion() {
return programVersion;
}
public void setProgramVersion(String programVersion) {
this.programVersion = programVersion;
}
public Boolean getDiscontinued() {
return discontinued;
}
public void setDiscontinued(Boolean discontinued) {
this.discontinued = discontinued;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public Boolean getDeletable() {
return deletable;
}
public void setDeletable(Boolean deletable) {
this.deletable = deletable;
}
@Column(nullable = false)
@Temporal(TemporalType.DATE)
@Index(name="Program_EffectiveDate_idx")
public Date getEffectiveDate() {
return effectiveDate;
}
public void setEffectiveDate(Date effectiveDate) {
this.effectiveDate = effectiveDate;
}
@Temporal(TemporalType.DATE)
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
@Column(nullable = false, length=255)
@Index(name="Program_Code_idx")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Column(length=255)
public String getDesciption() {
return desciption;
}
public void setDesciption(String desciption) {
this.desciption = desciption;
}
@Column(length=255)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean equals(Object obj) {
if((obj != null) && (obj.getClass() == this.getClass())) {
Long objId = ((Program)obj).getId();
if( objId != null && objId.equals(this.getId()) ){
return true;
}
}
return false;
}
}
这是分类:
package com.sg.pds.domain.entity.ratedelivery;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.CollectionTable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.JoinColumn;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import org.hibernate.annotations.Index;
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Classification extends BaseEntity{
//@XmlElement(name="code")
private String code;
private String description;
@XmlElement(name="liabilityLimit") @XmlElementWrapper(name = "liabilityLimits")
private Set<LiabilityLimit> liabilityLimits = new HashSet<LiabilityLimit>();
@XmlTransient
private Program program;
private String lobName;
private String lobCode;
private String premiumBaseValue;
private String premiumBaseDesc;
private String premiumBaseCode;
private String causeOfLoss;
@XmlElement(name="coverage") @XmlElementWrapper(name = "coverages")
private Set<String> coverages = new HashSet<String>();
//@XmlTransient
//private Set<Rate> rates = new HashSet<Rate>();
//@XmlTransient
//private Set<Criterion> criteria = new HashSet<Criterion>();
@XmlElement(name="territory") @XmlElementWrapper(name = "territories")
private Set<Territory> territories = new HashSet<Territory>();
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="classification")
public Set<Territory> getTerritories() {
return territories;
}
public void setTerritories(Set<Territory> territories) {
this.territories = territories;
}
//@OneToMany(mappedBy="classification")
//public Set<Criterion> getCriteria() {
// return criteria;
//}
//public void setCriteria(Set<Criterion> criteria) {
// this.criteria = criteria;
//}
//@OneToMany(mappedBy="classification")
//public Set<Rate> getRates() {
// return rates;
//}
//public void setRates(Set<Rate> rates) {
// this.rates = rates;
//}
@Column(length=255)
public String getPremiumBaseValue() {
return premiumBaseValue;
}
public void setPremiumBaseValue(String premiumBaseValue) {
this.premiumBaseValue = premiumBaseValue;
}
@Column(length=255)
public String getPremiumBaseDesc() {
return premiumBaseDesc;
}
public void setPremiumBaseDesc(String premiumBaseDesc) {
this.premiumBaseDesc = premiumBaseDesc;
}
@Column(length=255)
public String getPremiumBaseCode() {
return premiumBaseCode;
}
public void setPremiumBaseCode(String premiumBaseCode) {
this.premiumBaseCode = premiumBaseCode;
}
@Column(length=255)
public String getCauseOfLoss() {
return causeOfLoss;
}
public void setCauseOfLoss(String causeOfLoss) {
this.causeOfLoss = causeOfLoss;
}
@ElementCollection
@CollectionTable(name="Coverage", joinColumns=@JoinColumn(name="classification_id"))
@Column(name="name", length=255)
public Set<String> getCoverages() {
return coverages;
}
public void setCoverages(Set<String> coverages) {
this.coverages = coverages;
}
@ManyToOne
public Program getProgram() {
return program;
}
public void setProgram(Program program) {
this.program = program;
}
@OneToMany(cascade = {CascadeType.ALL}, mappedBy="classification")
@OrderBy("type ASC")
public Set<LiabilityLimit> getLiabilityLimits() {
return liabilityLimits;
}
public void setLiabilityLimits(Set<LiabilityLimit> liabilityLimits) {
this.liabilityLimits = liabilityLimits;
}
@Column(length=255)
@Index(name="Classification_Code_idx")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Column(length=255)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLobName() {
return lobName;
}
public void setLobName(String lobName) {
this.lobName = lobName;
}
public String getLobCode() {
return lobCode;
}
public void setLobCode(String lobCode) {
this.lobCode = lobCode;
}
public boolean equals(Object obj) {
if((obj != null) && (obj.getClass() == this.getClass())) {
Long objId = ((Classification)obj).getId();
if( objId != null && objId.equals(this.getId()) ){
return true;
}
}
return false;
}
}
这是我的会话工厂配置:
<bean id="sessionFactoryTester" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSourceLoader" />
<property name="packagesToScan" value="com.sg.pds.domain.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.jdbc.fetch_size">0</prop>
<!-- Enable Hibernate's automatic session context management -->
<prop key="current_session_context_class">jta</prop>
<!--
<prop key="hibernate.hbm2ddl.auto">validate</prop>
-->
</props>
</property>
</bean>
答案 0 :(得分:2)
这是因为JPA默认加载了ManyToOne关联。将fetch设置为lazy应该删除额外的连接。
答案 1 :(得分:0)
也许这是由bug引起的。您可以使用custom SQL for loading或其他解决方案解决错误。