JPQL+ MYSQL to get rid of `You can't specify target table XXX for update in FROM clause`

谁说胖子不能爱 提交于 2019-12-11 09:46:16

问题


There is an AccessLog table which logs which user (FK user_id) accesses which mail (FK mail_id) at which time(column created).

The table grows as time goes by. I want to keep the latest row (which user last accesses which mail) , removing all old logs.

The following SQL code works as expected:

delete from AccessLog where id not in (
  select id from (
    select a.id from AccessLog a
    where a.created = 
      (select max(b.created) from AccessLog b 
       where b.user_id = a.user_id 
       and   b.mail_id = a.mail_id
      )
    group by a.user_id , a.mail_id
  ) as tmpTable
)

The SQL is weird because of MySQL's limitation , and has been discussed many times in stackoverflow.com

Anyway , it works. But I want a version of JPA's Query Language.

I don't know how to make JPA 2 (with Hibernate implementation) generate such SQL code.

The only JPQL I can write is like this :

delete from AccessLog b where b not in (
  select a from AccessLog a
    where a.created = 
      (select max(b.created) from AccessLog b 
       where b.user = a.user 
       and b.mail = a.mail
      )
  group by a.user , a.mail
)

which generates MySQL-incompatable SQL :

Hibernate: 
    delete 
    from
        AccessLog 
    where
        id not in  (
            select
                log1_.id 
            from
                AccessLog log1_ 
            where
                log1_.created=(
                    select
                        max(log2_.created) 
                    from
                        AccessLog log2_ 
                    where
                        log2_.user_id=log1_.user_id 
                        and log2_.mail_id=log1_.mail_id
                ) 
            group by
                log1_.user_id ,
                log1_.mail_id)

And causes the famous error : MySQL can’t specify target table for update in FROM clause

I can sure use crontable execute the working SQL code regularly . But I want a JPQL version.

I wonder how to make JPQL generate mysql-compatible SQL code as mentioned ?

Another not-so-related question is how to translate such SQL

select a.* from AccessLog a inner join
  (select mail_id , user_id , max(created) as maxCreated
    from AccessLog b group by mail_id , user_id
    ) b
  on  a.mail_id = b.mail_id
  and a.user_id = b.user_id
  and a.created = b.maxCreated

to JPQL ?

It uses inner join to select which user last access which mail . But It seems unable to translate to JPQL .

Environments :

spring-data-jpa:jar:1.9.2
hibernate-jpa-2.1
MySQL 5.7.10

来源:https://stackoverflow.com/questions/34707267/jpql-mysql-to-get-rid-of-you-cant-specify-target-table-xxx-for-update-in-from

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!