QueryDsl日期算术问题(后面的PostgreSQL) - 函数add_minutes(...)不存在

时间:2016-12-30 18:44:48

标签: java spring postgresql jpql querydsl

我遇到QueryDsl日期算术问题。它对我不起作用,抛出以下错误:

Caused by: org.postgresql.util.PSQLException: ERROR: function add_minutes(timestamp with time zone, integer) does not exist

我正在使用PostgreSQL数据库,这是版本:

PostgreSQL 9.4.4 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2, 64-bit

QueryDsl版本为:3.7.4

这是查询代码:

import static com.experthub.ws.model.QExpertAppointmentStatusChangeEntity.expertAppointmentStatusChangeEntity;
import static com.mysema.query.support.Expressions.dateTimeOperation;
import static com.mysema.query.types.expr.BooleanExpression.allOf;

public class ExpertAppointmentRepositoryImpl implements ExpertAppointmentRepositoryCustom {

    private EntityManager entityManager;

    @Autowired
    public ExpertAppointmentRepositoryImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Integer getNumPendingAppointments(Integer userId, Date currentTime) {
        return (int) new JPAQuery(entityManager)
                .from(expertAppointmentStatusChangeEntity)
                .where(
                        allOf(
                                expertAppointmentStatusChangeEntity.expertAppointmentEntity().userExpertEntity().id.eq(userId),
                                dateTimeOperation(
                                        Date.class,
                                        Ops.DateTimeOps.ADD_MINUTES,
                                        expertAppointmentStatusChangeEntity.expertAppointmentEntity().appointmentTime,
                                        expertAppointmentStatusChangeEntity.expertAppointmentEntity().duration).after(currentTime)))
                .count();
    }

这就是实体的样子:

@Entity
@Table(name = "expert_appointment_status_change")
@EqualsAndHashCode(of = "id")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExpertAppointmentStatusChangeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "id_expert_appointment", nullable = false)
    private ExpertAppointmentEntity expertAppointmentEntity;

    @Column(name = "status", nullable = false)
    private Integer status;

    @Column(name = "change_time", nullable = false)
    private Date changeTime;

    @Column(name = "change_initiator", nullable = false)
    private Integer changeInitiator;

    @Column(name = "message", length = 512)
    private String message;
}
@Entity
@Table(name = "expert_appointment")
@EqualsAndHashCode(of = "id")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExpertAppointmentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "id_user", nullable = false)
    private UserEntity userEntity;

    @ManyToOne
    @JoinColumn(name = "id_user_expert", nullable = false)
    private UserEntity userExpertEntity;

    @Column(name = "appointment_time", nullable = false)
    private Date appointmentTime;

    @Column(name = "duration", nullable = false)
    private Integer duration;

    // some other fields

    @OneToMany(mappedBy = "expertAppointmentEntity")
    @OrderBy("changeTime DESC")
    private List<ExpertAppointmentStatusChangeEntity> expertAppointmentStatusChangeEntities;
}

我还没有找到任何其他方法来做这个算法。

我知道this class的存在,但我不确定如何将其整合到我的代码中。

也尝试这样做:

public class PostgreSQLJPQLTemplates extends JPQLTemplates {

    public PostgreSQLJPQLTemplates() {
        super();

        add(Ops.DateTimeOps.ADD_YEARS, "{0} + interval '{1s} years'");
        add(Ops.DateTimeOps.ADD_MONTHS, "{0} + interval '{1s} months'");
        add(Ops.DateTimeOps.ADD_WEEKS, "{0} + interval '{1s} weeks'");
        add(Ops.DateTimeOps.ADD_DAYS, "{0} + interval '{1s} days'");
        add(Ops.DateTimeOps.ADD_HOURS, "{0} + interval '{1s} hours'");
        add(Ops.DateTimeOps.ADD_MINUTES, "{0} + interval '{1s} minutes'");
        add(Ops.DateTimeOps.ADD_SECONDS, "{0} + interval '{1s} seconds'");
    }
}

并将其作为JPAQuery构造函数的第二个参数添加:

// somwhere in code
PostgreSQLJPQLTemplates template = new PostgreSQLJPQLTemplates();

new JPAQuery(entityManager, template)

只引起了不同的问题。

知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

您必须在方言中注册该功能。

public class BimDB2Dialect extends DB2Dialect {

public BimDB2Dialect() {
    registerFunction("add_years", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + ?2 years"));
    registerFunction("add_months", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + ?2 months"));
    registerFunction("add_weeks", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + 7 * ?2 days"));
    registerFunction("add_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + ?2 days"));

}

}

查看帖子Date arithemtic

答案 1 :(得分:0)

这对我来说适合postgres。

public class CustomPostgreSQL9Dialect extends PostgreSQL95Dialect{

    public CustomPostgreSQL9Dialect() {
        super();
        registerFunction("add_years", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + interval '1 years' * ?2"));
        registerFunction("add_months", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + interval '1 months' * ?2"));
        registerFunction("add_weeks", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + interval '1 days' * 7 * ?2"));
        registerFunction("add_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + interval '1 days' * ?2"));
        registerFunction("add_minutes", new SQLFunctionTemplate(StandardBasicTypes.DATE, "?1 + interval '1 minutes' * ?2"));
    }
}

设置休眠方言

hibernate.dialect=<package>.CustomPostgreSQL9Dialect