Пользовательский пункт присоединения для Hibernate Many To One - PullRequest
2 голосов
/ 13 октября 2011

Можно ли адаптировать запрос, который выполняет Hibernate при извлечении ассоциаций для данного объекта?Более конкретно, я хотел бы добавить дополнительное условие к предложению соединения, чтобы устранить недостатки дизайна в устаревшей базе данных, с которой я работаю.

Проблема, с которой я сталкиваюсь, ниже.Первичный ключ для таблицы b состоит из 2 полей: категории id и value_id.Однако в таблице A хранится только value_id, и предполагается, что идентификатор категории жестко задан:

@Entity
@Table(name = "table_a")
public class A {
   @ManyToOne
   @JoinColumn(name = "b_id")
   private B b;
}

@Entity
@Table(name = "table_b")
public class B {
   @Id
   private int id;
}

При запросе экземпляров A hibernate генерирует следующеепредложение join:

SELECT *
FROM table_a a LEFT OUTER JOIN table_b b
  ON a_.b_id = b_.value_id

В то время как они запрашивают, я должен выполнить его:

SELECT *
FROM table_a a LEFT OUTER JOIN table_b b
  ON a_.b_id = b_.value_id
 AND b.category_id = 2

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

Ответы [ 2 ]

1 голос
/ 25 января 2012

Я решил проблему.Это было не самое симпатичное решение, но единственное, которое сработало.

В основном мне пришлось сделать:

  1. Имитировать Embbeded ID для класса A
  2. Makea Соединение между A -> B с использованием столбца действительного ключа и categoryId по сравнению с формулой

Примерно так:

Obs: я не тестировал этот код, просто адаптировал его.

@Entity
@Table(name = "table_a")
public class A {
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumnsOrFormulas(value={
        @JoinColumnOrFormula(column=
                @JoinColumn(name="B_ID", referencedColumnName="B_ID")),
        @JoinColumnOrFormula(formula=
                @JoinFormula(referencedColumnName="CATEGORY_ID", 
                        value = "(SELECT 2 from DUAL)"))}) //I am using Oracle
   @JoinColumn(name = "b_id")
   private B b;
}

@Entity
@Table(name = "table_b")
class B {
   @Id
   private BId id;
}

@Embeddable
class BId{
    private int id;
    private Integer categoryId;
}
0 голосов
/ 13 октября 2011

Вы можете использовать это:

@OneToMany(mappedBy = "b")
@Cascade(CascadeType.ALL)
private List<A> aList = new ArrayList<A>(0);

на class B, чтобы получить объединение и именованный запрос, чтобы получить category_id (также в class B)

@NamedQueries({
@NamedQuery(name = "B.findByCategoryId", query = "SELECT b FROM B b WHERE b.Id = :categoryId")
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...