文章:Tomcat啟動很久才完成經過2週終於找到原因並成功解決了~
原因是hibernate的hbm.xml設定檔在Tomcat啟動時需先load至Tomcat memory,但是透過hbm.xml檔load至memory需要I/O及memory,故會花費許久,因table共70多個,而且有些table的欄位很多,故造成Tomcat需啟動許久。
我試了以下3種hbm.xml的設定均無法降低啟動時間:
<property name="mappingDirectoryLocations">
<list>
<value>classpath:com/xxx/bean/</value>
</list>
</property>
<property name="mappingLocations">
<list>
<value>classpath:com/xxx/bean/*.hbm.xml</value>
...
</list>
</property>
<property name="mappingResources">
<list>
<value>com/xxx/bean/PRCmdCfg.hbm.xml</value>
...
</list>
</property>
後來,試著將設定檔內sql調整成直接寫在程式內而不用hbm.xml設定的方式,啟動效能並未改善:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-mapping">
<hibernate-mapping>
<class name="com.xxx.bean.PRUnit" table="PRUnit">
...
</class>
<sql-query name="findPRUnitWithDetail">
<return alias="t1" class="com.xxx.bean.PRUnit"/>
<return alias="t2" class="com.xxx.bean.PRFuncCfg"/>
<return alias="t3" class="com.xxx.bean.PRCmdCfg"/>
<return alias="t4" class="com.xxx.bean.PRCode"/>
<return alias="t5" class="com.xxx.bean.PRCode"/>
<return alias="t7" class="com.xxx.bean.PRMenuCfg"/>
<![CDATA[
SELECT {t1.*}, {t2.*}, {t3.*}, {t4.*}, {t5.*}, {t7.*}
FROM PRUnit t1
JOIN PRFuncCfg t2
ON t1.platForm = t2.platForm
AND t1.funcId = t2.funcId
JOIN PRCmdCfg t3
ON t1.platForm = t3.platForm
AND t1.funcId = t3.funcId
AND t1.cmdId = t3.cmdId
JOIN PRCode t4
ON t4.CodeType = 'UNIT'
AND t1.unitId = t4.CodeId
JOIN PRCode t5
ON t5.CodeType = 'PLFM'
AND t1.platForm = t5.CodeId
JOIN PRMenuCfg t7
ON t2.platForm = t7.platForm
AND t2.menuId = t7.menuId
WHERE t1.unitId
in (SELECT t8.unitId
FROM PREmpUnit t8
WHERE t8.empId=:EmpId AND t8.cmdEnable = 1)
AND t1.cmdEnable = 1
]]>
</sql-query>
</hibernate-mapping>
最後,只好用最麻煩的方式,取消hbm.xml的設定,改為直接在class設定
...
@Entity
@Table(name = "PRUnit")
public class PRUnit implements Serializable {
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(
name = "platForm",
column = @Column(name = "platForm")),
@AttributeOverride(
name = "unitId",
column = @Column(name = "unitId")),
@AttributeOverride(
name = "funcId",
column = @Column(name = "funcId")),
@AttributeOverride(
name = "cmdId",
column = @Column(name = "cmdId"))
})
private PRUnitPK PRUnitPK;
@Column(name = "cmdEnable")
private int cmdEnable;
@Column(name = "cfgVal")
private String cfgVal;
@Column(name = "optVal")
private String optVal;
@Column(name = "modifyTime")
private Date modifyTime;
@Column(name = "modifyEmp")
private String modifyEmp;
public PRUnit() {
}
public PRUnit(PRUnitPK PK) {
this.PRUnitPK = PK;
}
public PRUnitPK getPRUnitPK() {
return PRUnitPK;
}
public void setPRUnitPK(PRUnitPK pRUnitPK) {
PRUnitPK = pRUnitPK;
}
public int getCmdEnable() {
return cmdEnable;
}
public void setCmdEnable(int cmdEnable) {
this.cmdEnable = cmdEnable;
}
public String getCfgVal() {
return cfgVal;
}
public void setCfgVal(String cfgVal) {
this.cfgVal = cfgVal;
}
public String getOptVal() {
return optVal;
}
public void setOptVal(String optVal) {
this.optVal = optVal;
}
public Date getModifyTime() {
return modifyTime;
}
public void setModifyTime(Date modifyTime) {
this.modifyTime = modifyTime;
}
public String getModifyEmp() {
return modifyEmp;
}
public void setModifyEmp(String modifyEmp) {
this.modifyEmp = modifyEmp;
}
@Override
public String toString() {
return "PRUnit [PRUnitPK=" + PRUnitPK + ", cmdEnable=" + cmdEnable + ", cfgVal=" + cfgVal + ", optVal=" + optVal
+ ", modifyTime=" + modifyTime + ", modifyEmp=" + modifyEmp + "]";
}
}
而applicationContext.xml調整為下面任一方式,Tomcat均能在1、2分鐘內啟動完畢
<property name="packagesToScan">
<list>
<value>com.xxx.bean</value>
</list>
</property>
<property name="mappingDirectoryLocations">
<list>
<value>classpath:com/xxx/bean/</value>
</list>
</property>
究其原因,猜測是hibernate在load hbm.xml需要花費較多的I/O及memory,故造成啟動花費超久,
剛開始使用此架構因table尚少沒感覺,等系統愈來愈大就開始造成困擾了~還好調整後能修正此問題,
要不然整個架構大改,就不是花幾天能完成的~
