0

I'm using Spring Boot 2.1, Hibernate 5.2.10 and I've a weird problem in a HQL query defined into a Spring Repository.

@Query(value = "SELECT m FROM Movement m LEFT JOIN FETCH m.wallet w LEFT JOIN FETCH w.contact c LEFT JOIN FETCH c.account acc JOIN FETCH m.checkPoint ck JOIN FETCH m.paymentType paymentType WHERE ((type(m)='MovementTicketBundle') OR (type(m)='MovementTicket') OR (type(m)='MovementRefund') OR ((type(m)='Movement') AND (m.wallet IS NULL)) )

I'm using the type() function becuase Movement has some subclasses

@Inheritance(strategy = InheritanceType.SINGLE_TABLE
@DiscriminatorColumn(name = "type")
 public class Movement extends AbstractEntity {

The query that Hibernate makes is:

Hibernate: select movement0_.`id` as id2_28_0_, wallet1_.`id` as id1_56_1_, contact2_.`id` as id1_9_2_, account3_.`id` as id1_0_3_, checkpoint4_.`id` as id1_6_4_, paymenttyp5_.`id` as id1_30_5_, movement0_.`createdBy` as createdB3_28_0_, movement0_.`createdDate` as createdD4_28_0_, movement0_.`lastModifiedBy` as lastModi5_28_0_, movement0_.`lastModifiedDate` as lastModi6_28_0_, movement0_.`sid` as sid7_28_0_, movement0_.`version` as version8_28_0_, movement0_.`amount` as amount9_28_0_, movement0_.`checkPoint_id` as checkPo13_28_0_, movement0_.`currencyDate` as currenc10_28_0_, movement0_.`description` as descrip11_28_0_, movement0_.`details` as details12_28_0_, movement0_.`paymentType_id` as payment14_28_0_, movement0_.`wallet_id` as wallet_15_28_0_, movement0_.`ticketBundle_id` as ticketB16_28_0_, movement0_.`refund_id` as refund_17_28_0_, movement0_.`ticket_id` as ticket_18_28_0_, movement0_.`type` as type1_28_0_, wallet1_.`createdBy` as createdB2_56_1_, wallet1_.`createdDate` as createdD3_56_1_, wallet1_.`lastModifiedBy` as lastModi4_56_1_, wallet1_.`lastModifiedDate` as lastModi5_56_1_, wallet1_.`sid` as sid6_56_1_, wallet1_.`version` as version7_56_1_, wallet1_.`balance` as balance8_56_1_, wallet1_.`balanceNotified` as balanceN9_56_1_, wallet1_.`balanceThreshold` as balance10_56_1_, wallet1_.`contact_id` as contact11_56_1_, contact2_.`createdBy` as createdB2_9_2_, contact2_.`createdDate` as createdD3_9_2_, contact2_.`lastModifiedBy` as lastModi4_9_2_, contact2_.`lastModifiedDate` as lastModi5_9_2_, contact2_.`sid` as sid6_9_2_, contact2_.`version` as version7_9_2_, contact2_.`account_id` as account25_9_2_, contact2_.`address` as address8_9_2_, contact2_.`city` as city9_9_2_, contact2_.`country` as country10_9_2_, contact2_.`duplicated` as duplica11_9_2_, contact2_.`emails` as emails12_9_2_, contact2_.`enabled` as enabled13_9_2_, contact2_.`fax` as fax14_9_2_, contact2_.`iban` as iban15_9_2_, contact2_.`landlinePhone` as landlin16_9_2_, contact2_.`mobilePhone` as mobileP17_9_2_, contact2_.`name` as name18_9_2_, contact2_.`pec` as pec19_9_2_, contact2_.`personType` as personT20_9_2_, contact2_.`sdiAccountId` as sdiAcco21_9_2_, contact2_.`swift` as swift22_9_2_, contact2_.`taxCode` as taxCode23_9_2_, contact2_.`vatNumber` as vatNumb24_9_2_, account3_.`createdBy` as createdB2_0_3_, account3_.`createdDate` as createdD3_0_3_, account3_.`lastModifiedBy` as lastModi4_0_3_, account3_.`lastModifiedDate` as lastModi5_0_3_, account3_.`sid` as sid6_0_3_, account3_.`version` as version7_0_3_, account3_.`enabled` as enabled8_0_3_, account3_.`lastPasswordUpdate` as lastPass9_0_3_, account3_.`password` as passwor10_0_3_, account3_.`roles` as roles11_0_3_, account3_.`type` as type12_0_3_, account3_.`username` as usernam13_0_3_, checkpoint4_.`createdBy` as createdB2_6_4_, checkpoint4_.`createdDate` as createdD3_6_4_, checkpoint4_.`lastModifiedBy` as lastModi4_6_4_, checkpoint4_.`lastModifiedDate` as lastModi5_6_4_, checkpoint4_.`sid` as sid6_6_4_, checkpoint4_.`version` as version7_6_4_, checkpoint4_.`closingTime` as closingT8_6_4_, checkpoint4_.`code` as code9_6_4_, checkpoint4_.`fiscalPrinterSerialNumber` as fiscalP10_6_4_, checkpoint4_.`name` as name11_6_4_, checkpoint4_.`openingTime` as opening12_6_4_, checkpoint4_.`stockThreshold` as stockTh13_6_4_, checkpoint4_.`type` as type14_6_4_, (SELECT COUNT(*) FROM TicketBlock t WHERE t.CheckPoint_id=checkpoint4_.id) as formula2_4_, (SELECT COALESCE(SUM(t.lastTicketNumber-t.nextTicketNumber+1),0) FROM TicketBlock t WHERE t.CheckPoint_id=checkpoint4_.id) as formula3_4_, paymenttyp5_.`createdBy` as createdB2_30_5_, paymenttyp5_.`createdDate` as createdD3_30_5_, paymenttyp5_.`lastModifiedBy` as lastModi4_30_5_, paymenttyp5_.`lastModifiedDate` as lastModi5_30_5_, paymenttyp5_.`sid` as sid6_30_5_, paymenttyp5_.`version` as version7_30_5_, paymenttyp5_.`code` as code8_30_5_, paymenttyp5_.`ecommerceEnabled` as ecommerc9_30_5_, paymenttyp5_.`editable` as editabl10_30_5_, paymenttyp5_.`genre` as genre11_30_5_, paymenttyp5_.`icon` as icon12_30_5_, paymenttyp5_.`name` as name13_30_5_, paymenttyp5_.`sorting` as sorting14_30_5_ from `Movement` movement0_ left outer join `Wallet` wallet1_ on movement0_.`wallet_id`=wallet1_.`id` left outer join `Contact` contact2_ on wallet1_.`contact_id`=contact2_.`id` left outer join `Account` account3_ on contact2_.`account_id`=account3_.`id` inner join `CheckPoint` checkpoint4_ on movement0_.`checkPoint_id`=checkpoint4_.`id` inner join `PaymentType` paymenttyp5_ on movement0_.`paymentType_id`=paymenttyp5_.`id` where (movement0_.`type`='MovementTicketBundle' or movement0_.`type`='MovementTicket' or movement0_.`type`='MovementRefund' or movement0_.`type`='Movement' and (movement0_.`wallet_id` is null))

Everything is fine but the brakets, in fact this part is wrong:

where (movement0_.`type`='MovementTicketBundle' or movement0_.`type`='MovementTicket' or movement0_.`type`='MovementRefund' or movement0_.`type`='Movement' and (movement0_.`wallet_id` is null))

It removes brackets from the condition Movement and wallet is null, I want this entire condition to be put in OR with others. Instead brackets are left just around (movement0_.wallet_idis null).

I tried to move brakets in serveral ways but the result is the same, so my guess is Hibernate rewrites the query as it thinks is right.

Am I doing something wrong, or is it a Hibernate's bug? Any hint or workaround?

drenda
  • 5,846
  • 11
  • 68
  • 141
  • From [this](https://stackoverflow.com/questions/1241142/sql-logic-operator-precedence-and-and-or), the logic should be the same, except the brackets are removed. – samabcde Feb 01 '20 at 14:16
  • Does this answer your question? [Brackets in HQL not ntranslated to SQL](https://stackoverflow.com/questions/13910195/brackets-in-hql-not-ntranslated-to-sql) – samabcde Feb 01 '20 at 14:18
  • I read that answers but it's different for me. I need brackets because the condition on the wallet should be verified only when type=Movement – drenda Feb 01 '20 at 14:27
  • But `And` has precedence over `Or`, hence the sql should return what you expected. – samabcde Feb 01 '20 at 14:32
  • I added brackets to alter precedence, but they are not present – drenda Feb 01 '20 at 14:49

0 Answers0