Hibernate игнорируя LEFT JOIN - PullRequest
       0

Hibernate игнорируя LEFT JOIN

2 голосов
/ 02 августа 2011

У меня есть таблица с именем SecurityContact, которая имеет отношение «многие к одному» с другой таблицей «Контакты».У него есть два столбца соединения с контактами, один из которых называется agentContact, а другой - audContact.Я пытаюсь выполнить следующий запрос HQL:

SELECT sc FROM SecurityContact sc LEFT JOIN sc.agentContact ac LEFT JOIN sc.auditContact ac2 WHERE sc.securityId=:securityId2

Однако Hibernate полностью игнорирует операторы LEFT JOIN и продолжает генерировать SQL, который использует внутренние объединения.Это совсем не подходит моим целям.Я попытался установить выборку аннотации без удачи.Эта проблема сводит меня с ума уже более двух дней, поэтому любая помощь будет высоко ценится.

Вот код для моего класса SecurityContact:

/**
 * The persistent class for the SecurityContact database table.
 * 
 */
@Entity
@FXClass(kind=FXClassKind.REMOTE)
public class SecurityContact implements Serializable {
    private static final long serialVersionUID = 1L;
    @Transient private String uid;
    @FXIgnore
    public String getUid() {
        if (uid == null) {
            uid = "" + securityContactId;
        }
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="securityContact_id")
    private Long securityContactId;

    @Column(name="security_id")
    private String securityId;

    @Column(name="create_date")
    private String createDate;

    @Column(name="create_user")
    private String createUser;

    @Column(name="modify_date")
    private String modifyDate;

    @Column(name="modify_user")
    private String modifyUser;

    //uni-directional many-to-one association to AgentContact

    @ManyToOne
    @JoinColumn(name="agent_id", referencedColumnName="contact_id")
    private Contact agentContact;

    //uni-directional many-to-one association to AuditContact
    @ManyToOne
    @JoinColumn(name="audit_id", referencedColumnName="contact_id")
    private Contact auditContact;

    public SecurityContact() {
    }
    @FXKeyColumn
    public Long getSecurityContactId() {
        return this.securityContactId;
    }

    public void setSecurityContactId(Long securityContactId) {
        this.securityContactId = securityContactId;
    }

    public String getSecurityId() {
        return this.securityId;
    }

    public void setSecurityId(String securityId) {
        this.securityId = securityId;
    }

    public String getCreateDate() {
        return this.createDate;
    }

    public void setCreateDate(String createDate) {
        this.createDate = createDate;
    }

    public String getCreateUser() {
        return this.createUser;
    }

    public void setCreateUser(String createUser) {
        this.createUser = createUser;
    }

    public String getModifyDate() {
        return this.modifyDate;
    }

    public void setModifyDate(String modifyDate) {
        this.modifyDate = modifyDate;
    }

    public String getModifyUser() {
        return this.modifyUser;
    }

    public void setModifyUser(String modifyUser) {
        this.modifyUser = modifyUser;
    }
    @FXManyToOne(parent="parent", property="contactId")
    public Contact getAgentContact() {
        return this.agentContact;
    }

    public void setAgentContact(Contact agentContact) {
        this.agentContact = agentContact;
    }
    @FXManyToOne(parent="parent", property="contactId")
    public Contact getAuditContact() {
        return this.auditContact;
    }

    public void setAuditContact(Contact auditContact) {
        this.auditContact = auditContact;
    }

} 

Вот сгенерированный SQL из приведенного выше HQL:

select securityco0_.agent_id as col_0_0_, securityco0_.audit_id as col_1_0_, securityco0_.create_date as col_2_0_, securityco0_.create_user as col_3_0_, securityco0_.modify_date as col_4_0_, securityco0_.modify_user as col_5_0_, securityco0_.securityContact_id as col_6_0_, securityco0_.security_id as col_7_0_, agentconta3_.contact_id as contact1_0_0_, agentconta4_.contact_id as contact1_0_1_, agentconta3_.bank_id as bank10_0_0_, agentconta3_.create_date as create2_0_0_, agentconta3_.create_user as create3_0_0_, agentconta3_.email as email0_0_, agentconta3_.fax as fax0_0_, agentconta3_.modify_date as modify6_0_0_, agentconta3_.modify_user as modify7_0_0_, agentconta3_.name as name0_0_, agentconta3_.phone as phone0_0_, agentconta4_.bank_id as bank10_0_1_, agentconta4_.create_date as create2_0_1_, agentconta4_.create_user as create3_0_1_, agentconta4_.email as email0_1_, agentconta4_.fax as fax0_1_, agentconta4_.modify_date as modify6_0_1_, agentconta4_.modify_user as modify7_0_1_, agentconta4_.name as name0_1_, agentconta4_.phone as phone0_1_ from SecurityContact securityco0_ left outer join AgentContact agentconta1_ on securityco0_.agent_id=agentconta1_.contact_id left outer join AgentContact agentconta2_ on securityco0_.audit_id=agentconta2_.contact_id inner join AgentContact agentconta3_ on securityco0_.agent_id=agentconta3_.contact_id inner join AgentContact agentconta4_ on securityco0_.audit_id=agentconta4_.contact_id where securityco0_.security_id=?

Ответы [ 2 ]

1 голос
/ 03 августа 2011

Я провел некоторое тестирование в отношении вашей проблемы, и мне кажется, что у вас должны быть проблемы с отображением или ошибка в (устаревшей) версии Hibernate, которую вы используете.

Для необязательной @ManyToOne ассоциации Hibernate уже должен использовать левое соединение для запроса объекта и его ассоциации (так как это единственный способ запросить корневой объект независимо от того, является ли связанный объектnull).

Я собрал пример проекта, который иллюстрирует это на https://github.com/mattnworb/hibernate-sample.

В моем примере проекта класс Employee имеет однонаправленное отображение "многие к одному"в Team класс :

/**
 * Unidirectional relationship between Employee and Team.
 */
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;

В модульных тестах есть и тест, согласно которому Employee.team ссылка не равна нулю, когда она установлена ​​в БД , и другой тест, который утверждает, что Employee.team является нулевым, если не задано в таблице БД.

Кроме того, существует аналогичное двунаправленное соотношение между Companyи Employee сущностей с аналогичными тестами.

Наконец, в журналах я вижу, что, когда Hibernate запрашивает сущность Employee (с простым session.get(Employee.class, id)), он использует левое соединение для извлечения таблицы teams (я сам добавлял разрывы строк):

DEBUG org.hibernate.SQL - выберите employee0_.id в качестве id1_2_, employee0_.company_id в качестве company6_1_2_, employee0_.dateOfBirth в качестве dateOfBi2_1_2_, employee0_.employmentStartDate как employee_1_0 employee_1_1_0_1_1_1_1_1, <имя_ут_1_1lastName в качестве lastName1_2_, employee0_.team_id в качестве team7_1_2_, company1_.id в качестве id0_0_, company1_.name в качестве name0_0_, team2_.id в качестве id2_1_, team2_.name в качестве name2_1_ <br>из сотрудников employee0_
в левой компании присоединиться к компании1.company_id = company1_.id
левые команды внешнего объединения team2_ on employee0_.team_id = team2_.id где employee0_.id =?

Таким образом, для суммирования Hibernate использует левое соединение междуваши связанные сущности, пока отношения установлены как необязательные, не должно быть необходимостиr специальные запросы HQL вообще - простой session.get() для корневого объекта должен запрашивать таблицу ассоциированного объекта с левым соединением.Если вы видите разные результаты, это говорит о том, что в вашей версии Hibernate есть ошибка (здесь я использую 3.6.6. Окончательный вариант), или что в вашем отображении есть что-то неправильное.

1 голос
/ 02 августа 2011

Ваш Синтаксис HQL-соединения выглядит странно. Попробуйте это:

SELECT sc
FROM SecurityContact sc
LEFT JOIN FETCH sc.agentContact
LEFT JOIN FETCH sc.auditContact
WHERE sc.securityId=:securityId2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...