简体   繁体   English

表被指定两次,既作为 'UPDATE' 的目标,也作为单独的数据源

[英]Table is specified twice, both as a target for 'UPDATE' and as a separate source for data

I use spring-jpa with hibernate implementation.我将 spring-jpa 与休眠实现一起使用。 I use mariadb and I try to do an update subquery我使用 mariadb 并尝试执行更新子查询

My object structure我的对象结构

@Entity
public class Room {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long roomId;

  @ManyToOne  
  @JoinColumn(name = "appartment_id")
  private Appartment appartment;
}

@Entity
public class Appartment {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long appartmentId;

  @OneToMany
  @JoinColumn(name="appartment_id")
  private Set<Room> roomList;
}

update Room r1
set r1.available = :availability
where r1.roomId in
( select r2.roomId from Room r2 JOIN r2.appartment a1 WHERE a1.appartmentId = :appartmentId )

I get this error我收到这个错误

java.sql.SQLException: Table 'room' is specified twice, both as a target for 'UPDATE' and as a separate source for data java.sql.SQLException: 表 'room' 被指定两次,既作为 'UPDATE' 的目标,也作为单独的数据源

This is a restriction in MySQL:-这是 MySQL 中的一个限制:-

http://dev.mysql.com/doc/refman/5.7/en/update.html http://dev.mysql.com/doc/refman/5.7/en/update.html

You cannot update a table and select from the same table in a subquery.您不能更新表并从子查询中的同一个表中进行选择。

There is a fudge you can do sometimes do to hide the sub query in aa further level of sub query that might work.有时您可以做一些事情来将子查询隐藏在可能有效的更高级别的子查询中。 Something like this (not tested):-像这样的东西(未经测试):-

UPDATE Room r1
SET r1.available = :availability
WHERE r1.roomId IN
    SELECT roomId
    FROM
    ( 
        SELECT r2.roomId 
        FROM Room r2 
        JOIN r2.appartment a1 
        WHERE a1.appartmentId = :appartmentId 
    )

Note that your query possibly has an error.请注意,您的查询可能有错误。 In the sub query you are joining the table Room aliased as r2 to a table called appartment on a database called r2.在子查询中,您将别名为 r2 的 Room 表连接到名为 r2 的数据库上名为 appartment 的表。 Also your sub query does a JOIN without a join condition.此外,您的子查询在没有连接条件的情况下执行 JOIN。

However you can quite possibly just do the join in the UPDATE statement without the need for a sub query:-但是,您很可能只需在 UPDATE 语句中进行连接,而无需子查询:-

UPDATE Room 
INNER JOIN r2.appartment a1
ON Room.roomId = a1.roomId
SET r1.available = :availability
WHERE a1.appartmentId = :appartmentId 

A solution will be to select roomIds seperatly and pass them as a parameter.一个解决方案是单独选择roomIds并将它们作为参数传递。

Select id list选择id列表

List<Long> roomIdList = entityManager.createQuery(
                    """SELECT r2.roomId 
                    FROM Room r2 
                    JOIN r2.appartment a1 
                    WHERE a1.appartmentId = :appartmentId""", Long.class)
                    .setParameter("appartmentId", appartmentId)
                    .getResultList();

Pass it as a parameter将其作为参数传递

int updated = entityManager.createQuery(
                    """UPDATE Room r1
                    SET r1.available = :availability
                    WHERE r1.roomId IN :roomIds""")
                    .setParameter("availability", availability)
                    .setParameter("roomIds", roomIdList)
                    .executeUpdate();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM