当前位置: 首页 > 知识库问答 >
问题:

使用Spring数据存储库和JPQL查询的JPA判别器

奚翰海
2023-03-14

我试图使用JPA继承来表示这些。

nnm\U tran实体

@Entity
@Table(name = "nnm_tran")
@IdClass(CommonTransactionKey.class)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "bargain_flag", discriminatorType = DiscriminatorType.CHAR)
@DiscriminatorValue("N")
public class CommonTransaction {

    @Id
    @Column(name = "id", nullable = false)
    private String transactionId;

    @Column(name = "plan_number", nullable = false)
    private String planNumber;

    @Column(name = "tran_date")
    private LocalDateTime transactionDatetime;

    @Column(name = "bargain_flag")
    private String bargainFlag;
    ...
}

便宜货实体

@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "bargains")
@DiscriminatorValue("B")
@PrimaryKeyJoinColumns({ @PrimaryKeyJoinColumn(name = "nnm_tran_id", referencedColumnName = "id"), @PrimaryKeyJoinColumn(name = "nnm_tran_source", referencedColumnName = "source") })
public class Bargain extends CommonTransaction implements Serializable {

    @Column(name = "unit_price")
    private BigDecimal unitPrice;

    @Column(name = "client_price")
    private BigDecimal clientPrice;
    ...
}

我认为到目前为止,这一切都连接正确。当我使用自定义查询附加Spring数据存储库时,我的问题就来了。

存储库

public interface CommonTransactionRepository extends CrudRepository<CommonTransaction, CommonTransactionKey> {

    @Query("select t from CommonTransaction t left join IoPlan p ON t.planNumber = p.planNumber "
        + "where (p.planNumber is NULL or p.planNumber = '') "
        + "and t.transactionDatetime between ?1 and ?2 "
        + "and t.cancelled = false")
    public Iterable<CommonTransaction> findOrphanedTransactionsByTranDate(LocalDateTime fromDate, LocalDateTime toDate);
   ...
}

当代理该方法并执行该方法时,它会生成SQL语句,选择不同的nnm\U tran。nnm\U tran t1 LEFT OUTER JOIN io\U plan t0 ON(t1.plan\U number=t0.plan\U number)中的讨价还价\U标志,其中(((t0.plan\U number为空)或(t0.plan\U number=?)和(t1.tran\u日期介于?和?)之间)和(t1.CANCELLED=?)

这样做的问题是nnm_tran表别名为t1,但鉴别器列引用了完整的表名nnm_tran.bargain_flag结果是一个可爱的

UnitOfWork(17171249)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'nnm_tran.bargain_flag' in 'field html" target="_blank">list'

这里的问题是,我是做错了什么,还是这是spring数据和/或eclipselink中的错误?

版本:spring data 1.7.2、Eclipselink 2.5.2、MySQL 5.6.28

共有1个答案

方轩昂
2023-03-14

以@manish的示例应用程序为起点,我开始重新分析缺失的复杂性,并很快发现了导致流氓SQL的原因。这取决于我在JPQL中执行的连接

注意:如果你是从未来来到这里的,那么请忽略此答案的其余部分,改为使用@Chris的评论。

大多数时候,我不需要查看甚至思考可以在查询中看到的IoPlan表

@Query("select t from CommonTransaction t left join IoPlan p ON t.planNumber = p.planNumber "
    + "where (p.planNumber is NULL or p.planNumber = '') "
    + "and t.transactionDatetime between ?1 and ?2 "
    + "and t.cancelled = false")

因此,此表不是作为字段的CommonTransaction实体的一部分。即使是这个查询的结果也不太重要,因为它只针对CommonTransaction进行一次性查询,在IoPlan表中没有关联的联接。

当我从@manish将连接重新添加到示例应用程序时,所有连接都以我的应用程序在EclipseLink中的相同方式中断,但在Hibernate中以不同的方式中断。Hibernate需要一个字段供您加入,如果您要求我这样做,将无法在查询中写入加入。事实上,在Hibernate中,您必须纯粹在JPA中定义连接,因此您最好在JPQL中使用点符号来访问它。

无论如何,按照这个想法,我尝试在我的CommonTransaction实体中添加一个虚拟字段来保存一个IoPlan,它几乎成功了。它默认了一些连接逻辑,但更接近

SELECT DISTINCT t1.bargain_flag FROM nnm_tran t1 LEFT OUTER JOIN io_plan t0 ON ((t0.ID = t1.IOPLAN_ID) AND (t1.plan_number = t0.plan_number)) WHERE ((((t0.plan_number IS NULL) OR (t0.plan_number = ?)) AND (t1.tran_date BETWEEN ? AND ?)) AND (t1.CANCELLED = ?))

在这种情况下,t1。IOPLAN\u ID和t0。ID不存在。因此,我最终在我的CommonTransaction实体中定义了整个连接

    @OneToOne
    @JoinColumn(insertable = false, updatable = false, name = "plan_number", referencedColumnName = "plan_number")
    private IoPlan ioPlan;

瞧,它开始工作了。这不太好,现在我有一个多余的连接条件

LEFT OUTER JOIN io_plan t1 
ON ((t1.plan_number = t0.plan_number) AND (t0.plan_number = t1.plan_number)) 

但我可以解决这个问题。我必须为它定义一个字段,这仍然很烦人,我实际上不想也不需要它,更不用说这个查询的结果返回的是没有IoPlan的CommonTransaction实体,因此该字段将永久为空。

 类似资料:
  • 我想知道是否有可能通过spring jpa存储库执行jpql查询,并能够使用分页作为排序功能,就像使用示例和规范一样。我想做一些类似的事情: QueryByQuestpleExector接口,即声明: JpaSpecificationExector接口声明:

  • 我想在中编写一个类似的查询,但它没有返回任何内容: -它不起作用。 一样完美。 以下是我的代码:

  • 目前我一直在使用以下Spring JPA存储库自定义查询, 我需要修改这个查询时,筛选文本将是逗号分隔的值。但按照以下方式,它将是一个动态查询,我如何执行它。 我需要构建动态查询,

  • 我的域类中有一个map属性,我正在尝试在存储库中创建一个查询,或者使用默认的“findByBlah”语法从数据库中提取属性。目前不起作用。我可以很容易地用SQL编写查询,但我不知道JPQL需要什么。如何使用JPQL或接口“findBy”语法从数据库中提取这些数据?无论我当前使用哪种存储库方法,当它从数据库中提取“收集器”时,属性(映射或复杂对象列表)始终为空。 域对象: 存储库: 这是在H2控制台

  • 使用Spring Boot应用程序。我有一个类UserService,我在其中创建了一个动态查询,根据请求参数具有多个or条件: 我有UserRepository接口,我需要执行这个查询。到目前为止,我使用了findById等JPA函数或@Query(“从事件中选择id”)。 如何将此查询从服务类传递到存储库并执行它?