Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在JPQL中引用仅为联接映射的列?_Java_Jpa_Jpql - Fatal编程技术网

Java 如何在JPQL中引用仅为联接映射的列?

Java 如何在JPQL中引用仅为联接映射的列?,java,jpa,jpql,Java,Jpa,Jpql,假设我有以下两张表: @Entity public class Foo { @Id private int id; @ManyToOne() @JoinColumn(name = "bar_id") private Bar bar; } @Entity public class Bar { @Id private int id; private Boolean flag; } 我想编写一个JPQL查询,根据一组Foo ID更改一些Bar.flag值 如果这是

假设我有以下两张表:

@Entity public class Foo {
   @Id private int id;
   @ManyToOne()
   @JoinColumn(name = "bar_id")
   private Bar bar;
}
@Entity public class Bar {
   @Id private int id;
   private Boolean flag;
}
我想编写一个JPQL查询,根据一组Foo ID更改一些Bar.flag值

如果这是纯SQL,我会这样写:

UPDATE Bar SET flag = true WHERE id IN (SELECT bar_id from FOO where id = 3);
UPDATE Bar bar SET bar.flag = true 
WHERE bar.id IN 
  (SELECT barFoo.id from FOO foo 
    JOIN foo.bar barFoo 
    WHERE foo.id = 3);
@Transactional
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) {
    final List<Bar> bars = findBarsForFooIds(fooIds);
    for (final Bar bar : bars) {
        bar.setFlag(newFlagValue);
    }
}

private List<Bar> findBarsForFooIds(final List<Integer> fooIds) {
    final TypedQuery<Bar> q =
            em.createQuery("select distinct b from Foo f join f.bar b where f.id in (:fooIds)",
                           Bar.class);
    q.setParameter("fooIds", fooIds);
    return q.getResultList();
}   
但是,您无法将其转换为JPQL,因为bar_id列未映射到实体的属性


由于bar_id没有直接映射到Foo实体上,如何在JPQL中实现这种查询?

您无法直接访问bar_id。您需要在Foo和bar之间进行额外的连接,以使用来自bar实体的id信息

因此,您的JPQL查询如下所示:

UPDATE Bar SET flag = true WHERE id IN (SELECT bar_id from FOO where id = 3);
UPDATE Bar bar SET bar.flag = true 
WHERE bar.id IN 
  (SELECT barFoo.id from FOO foo 
    JOIN foo.bar barFoo 
    WHERE foo.id = 3);
@Transactional
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) {
    final List<Bar> bars = findBarsForFooIds(fooIds);
    for (final Bar bar : bars) {
        bar.setFlag(newFlagValue);
    }
}

private List<Bar> findBarsForFooIds(final List<Integer> fooIds) {
    final TypedQuery<Bar> q =
            em.createQuery("select distinct b from Foo f join f.bar b where f.id in (:fooIds)",
                           Bar.class);
    q.setParameter("fooIds", fooIds);
    return q.getResultList();
}   

JPA的一个关键特性是从Java代码中抽象出基本的数据库细节,如外键。有多种方法可以实现您概述的查询,以下是几种方法:

@Transactional
public void updateBarFlagForFoo(final int fooId, final boolean newFlagValue) {
    final Foo foo = em.find(Foo.class, fooId);
    foo.getBar().setFlag(newFlagValue);
}
或散装:

@Transactional
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) {
    final Query query = em.createQuery(
        "update Bar b set flag = :newFlagValue where b.id in " +
            "(select f.bar.id from Foo f where f.id in (:fooIds))");
    query.setParameter("newFlagValue", newFlagValue);
    query.setParameter("fooIds", fooIds);
    query.executeUpdate();
}
不会更改实际的Foo对象

我更喜欢这样做:

UPDATE Bar SET flag = true WHERE id IN (SELECT bar_id from FOO where id = 3);
UPDATE Bar bar SET bar.flag = true 
WHERE bar.id IN 
  (SELECT barFoo.id from FOO foo 
    JOIN foo.bar barFoo 
    WHERE foo.id = 3);
@Transactional
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) {
    final List<Bar> bars = findBarsForFooIds(fooIds);
    for (final Bar bar : bars) {
        bar.setFlag(newFlagValue);
    }
}

private List<Bar> findBarsForFooIds(final List<Integer> fooIds) {
    final TypedQuery<Bar> q =
            em.createQuery("select distinct b from Foo f join f.bar b where f.id in (:fooIds)",
                           Bar.class);
    q.setParameter("fooIds", fooIds);
    return q.getResultList();
}   

当然,您可以创建一个@Column来映射bar_id,但我不建议这样做,因为它有点违背JPA的目的。

如果您想要一个工作批量更新查询,以下操作应该可以:

更新Bar b SET flag=true,其中b从FOO中选择f.Bar,其中id=3


这样做的目的是在进行子选择时使用实体。

集合在哪里?这不是答案吗@sashok_bg我还没有尝试过,但我认为不会,因为在他们的示例中,我没有在实体p.country_id中映射原始外键