2013-07-10 4 views
3

Мне нужно выбрать компании из базы данных с их активными адресами (address.address_status_id = 1). Если адрес неактивен, столбцы адресов должны содержать нули.Подзапрос в соединении

Следующий запрос делает именно то, что я хочу:

select c.id, c.name, a.id, a.street 
from company c 
left join 
(select * from address where address_status_id = 1) a 
on c.id = a.company_id 

Я попробовал это в Java/QueryDSL:

JPAQuery query = new JPAQuery(entityManager); 
query = query.from(qCompany); 
query = query.leftJoin(company.addresses, new JPASubQuery().from(qAddress)  
.where(qAddress.addressStatusId.eq(AddressStatuss.ACTIVE.asBigDecimal())).list(qAddress)); 

Однако JPA (и, следовательно, JPAQuery в QueryDSL) не поддерживает a subquery in a JOIN clause

Есть ли способ перефразировать инструкцию SQL, чтобы она могла быть выражена в JPA/QueryDSL?

Редактировать: Мы используем Oracle DB и Hibernate JPA-провайдера, если это имеет значение.

ответ

5

Может быть, как этот

select c.id, c.name, a.id, a.street 
from Company c 
left join c.addresses a on a.addressStatusId = 1 

и Querydsl

query.from(c) 
    .leftJoin(c.addresses, a) 
    .on(a.addressStatusId.eq(1)) 
    .list(c.id, c.name, a.id, a.street) 
+0

Ой, мы используем версию 2.9, и метод ON в нем, похоже, не существует. Я вижу, что это в 3.2.0. в JPAQueryBase. Мы попытались обновить некоторое время назад, но отложили его, увидев количество изменений, которые должны быть внесены для компиляции нашего кода. Может быть, метод ON заменил метод WITH? –

+0

Да, с (a.addressStatusId.eq (1)) делает именно то, что я хотел! –

+0

Да, 'on' заменен' на'. –

1

Я бы использовал Oracle DB JDBC. Вы можете получить это here.

В зависимости от того, как вы пытаетесь построить апплет или приложение, вам придется выбирать между крошечной и версией OCI JDBC. Дополнительная информация об этом here.

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

Class.forName("oracle.jdbc.OracleDriver"); 
Connection con = null; 
Statement stmt = null; 
ResultSet rset = null; 
try{ 
    con = DriverManager.getConnection("jdbc:oracle:oci:@//192.168.1.100", "user", "password"); 

    stmt = con.prepareStatement(); 

    rset = stmt.executeQuery("SELECT name, address, phonenumber FROM tbl_comanies"); 

    while(rset.next()){ 
     String name = rset.getString(1); 
     String address = rset.getString(2); 
     int phonenumber = rset.getInt(3); 
     //The number passed to the get...()-Method is the place in the SQL query. (Here, name=1, address=2, phonenumber=3) 
    } 
} catch (SQLException ex) { 
    System.out.println(ex.getMessage()); 
} finally { 
    try { 
     if(rset != null) 
      rset.close(); 
     if(stmt != null) 
      stmt.close(); 
     if(con != null) 
      con.close(); 
    } 
} 

Надеюсь, это поможет вам.

С уважением, Энди

+0

Слишком Oldschool, JDBC может быть и речи в нашем приложении. :) –

+0

Можете ли вы объяснить, почему это слишком старая школа или почему об этом не может быть и речи? – AndMim

+1

Существует множество причин, по которым это совершенно непригодно для крупных приложений, и почему подход, отличный от ORM, почти никогда не используется. Вам необходимо вручную сопоставить ResultSet с вашими бизнес-классами Java - кошмаром, подверженным ошибкам. Ваши имена таблиц и столбцов жестко закодированы в строках без проверки времени компиляции и безопасности типов. Что делать, если имя таблицы или столбца изменяется в БД - вы не будете знать, что что-то не так, пока вы не запустите конкретный код. Ваш код зависит от базы данных, что, если вы решите перейти с Oracle на MySQL позже? –