表格被指定两次,两者都作为'更新'的目标。并作为单独的数据来源

时间:2016-02-18 15:52:50

标签: java mysql jpa mariadb

我使用spring-jpa和hibernate实现。我使用mariadb,我尝试做一个更新子查询

我的对象结构

@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 )

我收到此错误

java.sql.SQLException:表&#39;房间&#39;被指定两次,两者都作为&#39;更新&#39;的目标。并作为数据的单独来源

2 个答案:

答案 0 :(得分:3)

这是MySQL的限制: -

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

您无法更新表并从子查询中的同一个表中进行选择。

你可以做一个软糖有时候做隐藏子查询的另一级子查询可能有效。这样的事情(未经测试): -

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 
    )

请注意,您的查询可能有错误。在子查询中,您将表名为r2的表连接到名为r2的数据库上名为appartment的表。此外,您的子查询在没有连接条件的情况下执行JOIN。

但是你很可能只需要在UPDATE语句中进行连接而不需要子查询: -

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

答案 1 :(得分:0)

一个解决方案是单独选择 roomIds 并将它们作为参数传递。

选择 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();

将其作为参数传递

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