2016-02-29 116 views
0

有一點與公式的樂趣,這讓我瘋狂。 我們有一些代碼可以通過公式獲取實體,數據庫中沒有鏈接,它需要在運行時完成,因此使用@Formula。下面是類的樣子:休眠公式沒有找到列名

@Entity 
@Table(name="T_EMPLOYEE_COMPANY_ASSIGNMENT" 
    ,schema="EXPENSES_MAIN" 
) 

public class EmployeeCompanyAssignment implements java.io.Serializable { 



public EmployeeCompanyAssignment() { 
} 

@EmbeddedId 
@AttributeOverrides({ 
    @AttributeOverride(name="employeeId", [email protected](name="EMPLOYEE_ID", nullable=false, precision=10, scale=0)), 
    @AttributeOverride(name="companyId", [email protected](name="COMPANY_ID", nullable=false, precision=10, scale=0)) }) 
public EmployeeCompanyAssignmentId getId() { 
    return this.id; 
} 
@ManyToOne(fetch=FetchType.LAZY) 
@JoinColumn(name="EMPLOYEE_ID", nullable=false, insertable=false, updatable=false) 
public Employee getEmployee() { 
    return this.employee; 
} 

public void setEmployee(Employee employee) { 
    this.employee = employee; 
} 
@ManyToOne(fetch=FetchType.LAZY) 
@JoinColumn(name="COMPANY_ID", nullable=false, insertable=false, updatable=false) 
public Company getCompany() { 
    return this.company; 
} 

public void setCompany(Company company){ 
    this.company = company; 
} 
@Column(name="DEFAULT_WBS_SAP_CODE", length=24) 
public String getDefaultWbsSapCode() { 
    return this.defaultWbsSapCode; 
} 

public void setDefaultWbsSapCode(String defaultWbsSapCode){ 
    this.defaultWbsSapCode = defaultWbsSapCode; 
} 
@Column(name="DEFAULT_COST_CENTER_SAP_CODE", length=10) 
public String getDefaultCostCenterSapCode() { 
    return this.defaultCostCenterSapCode; 
} 

public void setDefaultCostCenterSapCode(String defaultCostCenterSapCode){ 
    this.defaultCostCenterSapCode = defaultCostCenterSapCode; 
} 
.... 
} 

而且公式設置是這樣的:

@Formula(value = "(SELECT * FROM(" + 
     "Select *" + 
      " from T_COST_CENTER cc" + 
      " where cc.is_blocked_in_sap = 0" + 
       " and cc.is_deleted_in_sap = 0" + 
       " and cc.company_id in" + 
        " (SELECT TECA.COMPANY_ID" + 
         " FROM T_EMPLOYEE_COMPANY_ASSIGNMENT TECA" + 
         " WHERE TECA.EMPLOYEE_ID = EMPLOYEE_ID)" + 
     " and LTRIM(" + 
       "(SELECT *" + 
       " FROM (select TECA.DEFAULT_COST_CENTER_SAP_CODE" + 
         " from T_EMPLOYEE_COMPANY_ASSIGNMENT TECA" + 
         " WHERE TECA.EMPLOYEE_ID = EMPLOYEE_ID)" + 
       " where ROWNUM = 1)" + 
      ", '0') = LTRIM(cc.sap_code, '0')" + 
     " order by cc.sap_code DESC" + 
     ")" + 
     " WHERE ROWNUM = 1" + 
     ")") 
public CostCenter getDefaultCostCenter() { 
    return defaultCostCenter; 
} 
public void setDefaultCostCenter(CostCenter defaultCostCenter) { 
    this.defaultCostCenter = defaultCostCenter ; 
} 

@Formula(value="(" + 
     "SELECT *" + 
      " FROM (Select wbs.*" + 
       " from T_WORK_BREAKDOWN_STRUCTURE wbs" + 
       " LEFT OUTER JOIN T_Company c" + 
        " on wbs.company_id = c.id" + 
       " where wbs.sap_code in (select TECA.DEFAULT_WBS_SAP_CODE" + //We shouldn't have to do this this, but whenever I try to call the field DEFAULT_WBS_SAP_CODE direct in the formula, it complains it can't find it 
             " from T_EMPLOYEE_COMPANY_ASSIGNMENT TECA" + 
             " where TECA.EMPLOYEE_ID = EMPLOYEE_ID)" + 
        " and wbs.is_blocked_in_sap = 0" + 
        " and wbs.is_deleted_in_sap = 0" + 
       " order by wbs.sap_code DESC)" + 
     " WHERE ROWNUM = 1"+ 
     ")") 
public WorkBreakdownStructure getDefaultWbs() { 
    return defaultWbs; 
} 
public void setDefaultWbs(WorkBreakdownStructure defaultWbs) { 
    this.defaultWbs = defaultWbs; 
} 

現在,原來我用的是列DEFAULT_COST_CENTER_SAP_CODE和DEFAULT_WBS_SAP_CODE的情況下直接內部的選擇,但得到錯誤無效的標識符,所以我想我會嘗試使用ID來引用,但是也會出現無效的標識符。這裏是休眠產生的SQL代碼:

2016-02-29 09:07:49,810 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:104) [rw] - select employeeco0_.EMPLOYEE_ID as EMPLOYEE2_33_1_, employeeco0_.COMPANY_ID as COMPANY1_34_1_, employeeco0_.EMPLOYEE_ID as EMPLOYEE2_34_1_, employeeco0_.COMPANY_ID as COMPANY1_34_0_, employeeco0_.EMPLOYEE_ID as EMPLOYEE2_34_0_, employeeco0_.DEFAULT_COST_CENTER_SAP_CODE as DEFAULT7_34_0_, employeeco0_.DEFAULT_WBS_SAP_CODE as DEFAULT8_34_0_, (SELECT * FROM(Select * from T_COST_CENTER cc where cc.is_blocked_in_sap = 0 and cc.is_deleted_in_sap = 0 and cc.company_id in (SELECT TECA.COMPANY_ID FROM T_EMPLOYEE_COMPANY_ASSIGNMENT TECA WHERE TECA.EMPLOYEE_ID = employeeco0_.EMPLOYEE_ID) and LTRIM((SELECT * FROM (select TECA.DEFAULT_COST_CENTER_SAP_CODE from T_EMPLOYEE_COMPANY_ASSIGNMENT TECA WHERE TECA.EMPLOYEE_ID = employeeco0_.EMPLOYEE_ID) where ROWNUM = 1), '0') = LTRIM(cc.sap_code, '0') order by cc.sap_code DESC) WHERE ROWNUM = 1) as formula2_0_, (SELECT * FROM (Select wbs.* from T_WORK_BREAKDOWN_STRUCTURE wbs LEFT OUTER JOIN T_Company c on wbs.company_id = c.id where wbs.sap_code in (select TECA.DEFAULT_WBS_SAP_CODE from T_EMPLOYEE_COMPANY_ASSIGNMENT TECA where TECA.EMPLOYEE_ID = employeeco0_.EMPLOYEE_ID) and wbs.is_blocked_in_sap = 0 and wbs.is_deleted_in_sap = 0 order by wbs.sap_code DESC) WHERE ROWNUM = 1) as formula3_0_ from EXPENSES_MAIN.T_EMPLOYEE_COMPANY_ASSIGNMENT employeeco0_ where (employeeco0_.COMPANY_ID in (select c.id from T_COMPANY c where c.is_deleted_in_sap =0)) and employeeco0_.EMPLOYEE_ID=? order by employeeco0_.COMPANY_ID

2016-02-29 09:07:49,811 TRACE org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:83) [rw] - binding parameter [1] as [BIGINT] - 28250

2016-02-29 09:07:49,811 TRACE org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:83) [rw] - binding parameter [1] as [BIGINT] - 28250

2016-02-29 09:07:49,811 TRACE org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:83) [rw] - binding parameter [1] as [BIGINT] - 28250

2016-02-29 09:07:49,817 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions(SqlExceptionHelper.java:143) [rw] - SQL Error: 904, SQLState: 42000

2016-02-29 09:07:49,817 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions(SqlExceptionHelper.java:143) [rw] - SQL Error: 904, SQLState: 42000

2016-02-29 09:07:49,817 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions(SqlExceptionHelper.java:144) [rw] - ORA-00904: "EMPLOYEECO0_"."EMPLOYEE_ID": invalid identifier

2016-02-29 09:07:49,817 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions(SqlExceptionHelper.java:144) [rw] - ORA-00904: "EMPLOYEECO0_"."EMPLOYEE_ID": invalid identifier

任何人都可以看到問題來自哪裏?這一切似乎都相當奇特...

這是在Oracle SQL環境中使用IntelliJ完成的。沒有公式,這類工作正常

編輯

我已經更新了一個函數公式,在測試多一點,看看我能做些什麼,我有這麼以下工作:

@OneToOne 
@JoinColumnsOrFormulas({ 
     @JoinColumnOrFormula([email protected]("(SELECT * FROM (" + 
       "SELECT WBS.ID FROM T_WORK_BREAKDOWN_STRUCTURE WBS" + 
       " LEFT OUTER JOIN T_COMPANY c" + 
       " ON WBS.COMPANY_ID = C.ID" + 
       " WHERE"+ 
       " WBS.IS_BLOCKED_IN_SAP = 0" + 
       " AND WBS.IS_DELETED_IN_SAP = 0" + 
       " ORDER BY WBS.SAP_CODE DESC)" + 
       "WHERE ROWNUM=1)")) 
}) 
public WorkBreakdownStructure getDefaultWbs() { 
    return defaultWbs; 
} 

但是,一旦我加入這一行的where子句:

WBS.SAP_CODE IN (SELECT TECA.DEFAULT_WBS_SAP_CODE FROM T_EMPLOYEE_COMPANY_ASSIGNMENT TECA WHERE TECA.EMPLOYEE_ID = EMPLOYEE_ID) 

還是這個:

WBS.SAP_CODE = DEFAULT_WBS_SAP_CODE 

它無法與無效的標識符(在EMPLOYEE_ID和DEFAULT_WBS_SAP_CODE分別地),但這些字段,它產生用於它在填充屬性的SQL代碼使用。測試在數據庫中直接生成的SQL作品。生成的工作的SQL代碼如下所示:

select 
    employeeco0_.COMPANY_ID as COMPANY1_34_, 
    employeeco0_.EMPLOYEE_ID as EMPLOYEE2_34_, 
    employeeco0_.DEFAULT_COST_CENTER_SAP_CODE as DEFAULT7_34_, 
    employeeco0_.DEFAULT_WBS_SAP_CODE as DEFAULT8_34_, 
    (SELECT 
     * 
    FROM 
     (SELECT 
      WBS.ID 
     FROM 
      T_WORK_BREAKDOWN_STRUCTURE WBS 
     LEFT OUTER JOIN 
      T_COMPANY c 
       ON WBS.COMPANY_ID = C.ID 
     WHERE 
      WBS.IS_BLOCKED_IN_SAP = 0 
      AND WBS.IS_DELETED_IN_SAP = 0 
     ORDER BY 
      WBS.SAP_CODE DESC) 
    WHERE 
     ROWNUM=1 
    ) as formula9_ 
from 
    EXPENSES_MAIN.T_EMPLOYEE_COMPANY_ASSIGNMENT employeeco0_ 

而失敗看起來像這樣的一個:

select 
    employeeco0_.COMPANY_ID as COMPANY1_34_, 
    employeeco0_.EMPLOYEE_ID as EMPLOYEE2_34_, 
    employeeco0_.DEFAULT_COST_CENTER_SAP_CODE as DEFAULT7_34_, 
    employeeco0_.DEFAULT_WBS_SAP_CODE as DEFAULT8_34_, 
    (SELECT 
     * 
    FROM 
     (SELECT 
      WBS.ID 
     FROM 
      T_WORK_BREAKDOWN_STRUCTURE WBS 
     LEFT OUTER JOIN 
      T_COMPANY c 
       ON WBS.COMPANY_ID = C.ID 
     WHERE 
      WBS.SAP_CODE IN (
       SELECT 
        TECA.DEFAULT_WBS_SAP_CODE 
       FROM 
        T_EMPLOYEE_COMPANY_ASSIGNMENT TECA 
       WHERE 
        TECA.EMPLOYEE_ID = employeeco0_.EMPLOYEE_ID 
      ) 
      AND WBS.IS_BLOCKED_IN_SAP = 0 
      AND WBS.IS_DELETED_IN_SAP = 0 
     ORDER BY 
      WBS.SAP_CODE DESC) 
     WHERE 
      ROWNUM=1) as formula9_ 
    from 
     EXPENSES_MAIN.T_EMPLOYEE_COMPANY_ASSIGNMENT employeeco0_ 

或者它看起來是這樣的:

select 
    employeeco0_.COMPANY_ID as COMPANY1_34_, 
    employeeco0_.EMPLOYEE_ID as EMPLOYEE2_34_, 
    employeeco0_.DEFAULT_COST_CENTER_SAP_CODE as DEFAULT7_34_, 
    employeeco0_.DEFAULT_WBS_SAP_CODE as DEFAULT8_34_, 
    (SELECT 
     * 
    FROM 
     (SELECT 
      WBS.ID 
     FROM 
      T_WORK_BREAKDOWN_STRUCTURE WBS 
     LEFT OUTER JOIN 
      T_COMPANY c 
       ON WBS.COMPANY_ID = C.ID 
     WHERE 
      WBS.SAP_CODE = employeeco0_.DEFAULT_WBS_SAP_CODE 
      AND WBS.IS_BLOCKED_IN_SAP = 0 
      AND WBS.IS_DELETED_IN_SAP = 0 
     ORDER BY 
      WBS.SAP_CODE DESC) 
    WHERE 
     ROWNUM=1 
    ) as formula9_ 
from 
    EXPENSES_MAIN.T_EMPLOYEE_COMPANY_ASSIGNMENT employeeco0_ 

然而,這完成後的作品在數據庫中(當您使用有效的ID替換employeeco0_.EMPLOYEE_ID或DEFAULT_WBS_SAP_CODE時)。希望此更新有所幫助

回答

0

這個問題是由於Oracle SQL無法引用在內部查詢的外部查詢中聲明的列造成的。我必須重新思考和重做查詢,以便我不需要在內部查詢中引用字段DEFAULT_WBS_SAP_CODE或EMPLOYEE_ID

1

在使用Formula和hibernate之前,我會嘗試直接在數據庫中運行查詢,以瞭解查詢的哪部分是錯誤的。

看着你的@Formula,我只看到「select *」:你不能像使用@ManyToOne一樣使用公式返回完全託管的實體。

您必須在String或Interger中使用@Formula。@Formula中的選擇必須具有單個列

此外,公式與實體一起提取,由於查詢的複雜性以及90%的時間不會使用,它會嚴重影響性能。也許在你的情況下,它可能值得它不使用公式

+0

我已經更新了代碼,以便它現在只返回所需實體的ID,並且可以獲取只要我不使用實體中的任何屬性或具有實體屬性的子選擇符,它就可以工作。 至於使用其他的東西比公式,這是不可能的,我重構遺留代碼,但不能更改數據庫,這個領域,ust手動完成,必須通過實體框架 – Draken

+0

這似乎是問題: http://stackoverflow.com/questions/10092320/reference-parent-query-column-in-subquery-oracle – Draken