使用 JPA 查询视图会返回奇怪的结果
Posted
技术标签:
【中文标题】使用 JPA 查询视图会返回奇怪的结果【英文标题】:Querying a view with JPA returns weird results 【发布时间】:2019-02-19 19:45:49 【问题描述】:这是我的视图数据:
30.0 120.0 1500.0 16 30.0 120.0 4000.0 16 30.0 140.0 1500.0 16 30.0 140.0 4000.0 16 35.0 130.0 2750.0 18 40.0 120.0 1500.0 16 40.0 120.0 4000.0 16 40.0 140.0 1500.0 16 40.0 140.0 4000.0 16
这是我的代码:
public List<Duplicate> getData()
EntityManagerFactory emf = Persistence.createEntityManagerFactory("DXSorterPU");
EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
List<Duplicate> result = entityManager.createQuery("SELECT d FROM Duplicate d").getResultList();
for (Duplicate d : result)
System.out.println(d.getF1()+" " +d.getF3()+" "+ d.getF4()+" "+ d.getResult()) ;
entityManager.getTransaction().commit();
entityManager.close();
return result;
这是我用上面的代码得到的数据:
30.0 120.0 1500.0 16 30.0 120.0 1500.0 16 30.0 120.0 1500.0 16 30.0 120.0 1500.0 16 35.0 130.0 2750.0 18 40.0 120.0 1500.0 16 40.0 120.0 1500.0 16 40.0 120.0 1500.0 16 40.0 120.0 1500.0 16
为什么结果不一样?请帮帮我。
这是我的重复课:
package dxsorter;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@Table(name = "DUPLICATE")
@XmlRootElement
@NamedQueries(
@NamedQuery(name = "Duplicate.findAll", query = "SELECT d FROM Duplicate d")
, @NamedQuery(name = "Duplicate.findByF1", query = "SELECT d FROM Duplicate d WHERE d.f1 = :f1")
, @NamedQuery(name = "Duplicate.findByF3", query = "SELECT d FROM Duplicate d WHERE d.f3 = :f3")
, @NamedQuery(name = "Duplicate.findByF4", query = "SELECT d FROM Duplicate d WHERE d.f4 = :f4")
, @NamedQuery(name = "Duplicate.findByResult", query = "SELECT d FROM Duplicate d WHERE d.result = :result"))
public class Duplicate implements Serializable
private static final long serialVersionUID = 1L;
// @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Basic(optional = false)
@Column(name = "F1")
@Id
private BigDecimal f1;
@Basic(optional = false)
@Column(name = "F3")
private BigDecimal f3;
@Basic(optional = false)
@Column(name = "F4")
private BigDecimal f4;
@Basic(optional = false)
@Column(name = "RESULT")
private int result;
public Duplicate()
public BigDecimal getF1()
return f1;
public void setF1(BigDecimal f1)
this.f1 = f1;
public BigDecimal getF3()
return f3;
public void setF3(BigDecimal f3)
this.f3 = f3;
public BigDecimal getF4()
return f4;
public void setF4(BigDecimal f4)
this.f4 = f4;
public int getResult()
return result;
public void setResult(int result)
this.result = result;
public List<Duplicate> getData()
EntityManagerFactory emf = Persistence.createEntityManagerFactory("DXSorterPU");
EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
List<Duplicate> result = entityManager.createQuery("SELECT d FROM Duplicate d").getResultList();
for (Duplicate d : result)
System.out.println(d.getF1()+" " +d.getF3()+" "+ d.getF4()+" "+ d.getResult()) ;
entityManager.getTransaction().commit();
entityManager.close();
return result;
【问题讨论】:
应该是 d.getF1()+" " + d.getF2() + " " + d.getF3()+" "+ d.getF4()? 我的视图中没有 F2 列。只有 4 列(F1、F3、F4 和结果)。 显示你的Duplicate
声明
JPA 不会修改您的查询数据。您的视图查询有问题!
我想得到准确的视图数据,因为我的视图数据是正确的。
【参考方案1】:
您的问题是您使用 @Id
(F1) 注释的列在您的视图中不是唯一的。
您的 JPA 提供程序(例如 hibernate)假定 F1
的值在视图中是唯一的。
这就是执行查询时发生的情况:
假设获取的第一行是
30.0 120.0 1500.0 16
.
您的 JPA 提供程序将此行与 id 30.0
(F1 列的值)相关联。
假设提取的下一行是30.0 120.0 4000.0 16
。现在,我们可以看到这一行与第一行不同。但是您的 JPA 提供者不知道这一点。提供者看到的是该行的id
的值为30
。因为他已经获取了具有该 ID 的行(并将其保存在会话/缓存中),所以他认为这是同一行。因此,他没有为第二行创建新对象,而是从第一行放置相同的对象。
为了解决这个问题,您应该创建一个真正的id
列(在视图中将具有唯一值)或使用原始 SQL 查询。
向视图添加 ID 列
MySQL:
您可以使用 mysql 中的 UUID()
函数向视图添加唯一标识符。这解释了here。
使用 UUID,您的选择应如下所示:
SELECT UUID() as ID, FACTORS.F1, FACTORS.F3, FACTORS.F4, COUNT() AS RESULT FROM APP.FACTORS GROUP BY FACTORS.F1, FACTORS.F3, FACTORS.F4 HAVING COUNT() > 1
我在 rextester 上创建了一个简单的示例。您可以查看here。
德比:
在 derby 中,您可以使用 ROW_NUMBER()
函数。
您的选择应如下所示:
SELECT ROW_NUMBER() OVER () as ID, FACTORS.F1, FACTORS.F3, FACTORS.F4, COUNT() AS RESULT FROM APP.FACTORS GROUP BY FACTORS.F1, FACTORS.F3, FACTORS.F4 HAVING COUNT() > 1
【讨论】:
这是我创建视图的sql,如何添加ID列?选择 FACTORS.F1, FACTORS.F3, FACTORS.F4, COUNT() 作为 APP.FACTORS GROUP BY FACTORS.F1, FACTORS.F3, FACTORS.F4 的结果有 COUNT() > 1跨度> @user9753394 我编辑了答案并添加了选择。 错误:“UUID”未被识别为函数或过程。我在 netbeans 中使用 derby。 您使用的是什么类型的数据库?我的例子是在 MYSQL 中。我在答案的底部添加了一个 mysql 示例。 我在 netbeans 中使用 java derby 数据库以上是关于使用 JPA 查询视图会返回奇怪的结果的主要内容,如果未能解决你的问题,请参考以下文章