正在将 Spring 应用程序从 Hibernate 4.3.1.Final 迁移到 5.4.27.Final
Migrating Spring application from Hibernate 4.3.1.Final to 5.4.27.Final
我正在尝试在旧的 Spring 应用程序中从休眠 4.3.1.Final 迁移到 5.4.27.Final(大多数 Spring 组件都在版本 4.3 上。13.Final).在更新版本修复几个小问题(class 导入)并使用 Maven 构建应用程序后,我在尝试在 Tomcat 7.0.107 上部署此 Web 应用程序时收到以下错误(部分堆栈跟踪指向到根例外):
2121 Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List hr.chus.plus.dao.repository.StatusUpdateRepository .findAlarmLogsByZoneAndDatesAndNeedsAck(java.lang.Integer,java.lang.String,java.util.Date,java.util.Date)!
-- cut --
2150 Caused by: org.hibernate.QueryException: Could not resolve identifier `acks` as plural-attribute [FROM hr.chus.plus.dao.model.jpa.StatusUpdate WHERE updateType='ALARM' AND relatedId=:alarmId AND subtype='ZONE' AND subtypeUuid=:zone AND timestamp BETWEEN :start AND :end AND needAck=true AND size(acks)=0]
2151 at org.hibernate.QueryException.generateQueryException(QueryException.java:120) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2152 at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2153 at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2154 at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2155 at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2156 at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2157 at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2158 at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:604) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2159 at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:716) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2160 ... 79 common frames omitted
2161 Caused by: org.hibernate.QueryException: Could not resolve identifier `acks` as plural-attribute
2162 at org.hibernate.hql.internal.ast.tree.CollectionPathNode.from(CollectionPathNode.java:123) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
这个 JPQL 是 运行 并且可以很好地部署以前的版本。
上述实体的相关部分如下:
报警日志:
@Entity
@Table(name = "z_alarm_log")
@SecondaryTable(name = "z_alarm_log_data", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "id") })
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class AlarmLog extends AbstractLogEntity {
private static final int SUBTYPE_MAX_LENGTH = 10;
@Column(name = "alarm_id")
private Integer alarmId;
@Column(name = "trouble", columnDefinition = "TINYINT")
private Boolean trouble;
@Lob
@Basic(fetch = FetchType.EAGER)
@Column(name = "data", columnDefinition = "BLOB", table = "z_alarm_log_data")
private String data;
@Column(name = "need_ack", columnDefinition = "TINYINT")
private Boolean needAck = false;
@OneToMany(mappedBy = "log", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private Set<AlarmLogAck> acks = new HashSet<>();
@Column(name = "code", nullable = false)
private int code = 0;
@Column(name = "subtype", length = SUBTYPE_MAX_LENGTH)
private String subtype;
@Column(name = "subtype_id")
private Integer subtypeId;
@Column(name = "subtype_uuid", nullable = true, columnDefinition = "CHAR")
private String subtypeUuid;
AlarmLogAck:
@Entity
@Table(name = "z_alarm_log_ack")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AlarmLogAck extends AbstractLongIdEntity {
private static final int MESSAGE_MAX_LENGTH = 200;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "zipato_id")
private Zipato zipato;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "log_id")
private AlarmLog log;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
private User user;
@Column(name = "show_date", nullable = false, columnDefinition = "DATETIME")
private Date showDate;
@Column(name = "ack_date", nullable = true, columnDefinition = "DATETIME")
private Date ackDate;
@Column(name = "message", length = MESSAGE_MAX_LENGTH, nullable = true)
private String message;
AlarmLogRepository:
@Transactional(readOnly = true)
public interface AlarmLogRepository extends JpaRepository<AlarmLog, Long>, JpaSpecificationExecutor<AlarmLog> {
@Query("FROM AlarmLog " + //
"WHERE zipato=:zipato " + //
" AND alarmId=:alarmId " + //
" AND subtype='ZONE' " + //
" AND subtypeUuid=:zone " + //
" AND timestamp BETWEEN :start AND :end" + //
" AND needAck=true " + //
" AND size(AlarmLog.acks)=0")
List<AlarmLog> findAlarmLogsByZoneAndDatesAndNeedsAck(@Param("zipato") Zipato p_zipato,
@Param("alarmId") Integer p_alarmId,
@Param("zone") String p_zone,
@Param("start") Date p_start,
@Param("end") Date p_end);
我尝试用谷歌搜索这个错误,但找不到 plural-attribute
无法识别的确切组合。我还尝试调试到一定程度,发现此 Set
未被识别为 Collection 类型,或者更准确地说 acks Set
不在列表中,因此无法被识别为plural-attribute
.
我不知道如何解决这个问题...
有什么想法吗?
对于该查询,您应该为实体设置标识符 AlarmLog
并按以下方式在 where 条件中使用该标识符:
...
@Query("FROM AlarmLog al " +
"WHERE zipato=:zipato " +
" AND alarmId=:alarmId " +
" AND subtype='ZONE' " +
" AND subtypeUuid=:zone " +
" AND timestamp BETWEEN :start AND :end" +
" AND needAck=true " +
" AND size(al.acks)=0")
...
我正在尝试在旧的 Spring 应用程序中从休眠 4.3.1.Final 迁移到 5.4.27.Final(大多数 Spring 组件都在版本 4.3 上。13.Final).在更新版本修复几个小问题(class 导入)并使用 Maven 构建应用程序后,我在尝试在 Tomcat 7.0.107 上部署此 Web 应用程序时收到以下错误(部分堆栈跟踪指向到根例外):
2121 Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List hr.chus.plus.dao.repository.StatusUpdateRepository .findAlarmLogsByZoneAndDatesAndNeedsAck(java.lang.Integer,java.lang.String,java.util.Date,java.util.Date)!
-- cut --
2150 Caused by: org.hibernate.QueryException: Could not resolve identifier `acks` as plural-attribute [FROM hr.chus.plus.dao.model.jpa.StatusUpdate WHERE updateType='ALARM' AND relatedId=:alarmId AND subtype='ZONE' AND subtypeUuid=:zone AND timestamp BETWEEN :start AND :end AND needAck=true AND size(acks)=0]
2151 at org.hibernate.QueryException.generateQueryException(QueryException.java:120) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2152 at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2153 at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2154 at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2155 at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2156 at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2157 at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2158 at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:604) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2159 at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:716) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
2160 ... 79 common frames omitted
2161 Caused by: org.hibernate.QueryException: Could not resolve identifier `acks` as plural-attribute
2162 at org.hibernate.hql.internal.ast.tree.CollectionPathNode.from(CollectionPathNode.java:123) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
这个 JPQL 是 运行 并且可以很好地部署以前的版本。
上述实体的相关部分如下:
报警日志:
@Entity
@Table(name = "z_alarm_log")
@SecondaryTable(name = "z_alarm_log_data", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "id") })
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class AlarmLog extends AbstractLogEntity {
private static final int SUBTYPE_MAX_LENGTH = 10;
@Column(name = "alarm_id")
private Integer alarmId;
@Column(name = "trouble", columnDefinition = "TINYINT")
private Boolean trouble;
@Lob
@Basic(fetch = FetchType.EAGER)
@Column(name = "data", columnDefinition = "BLOB", table = "z_alarm_log_data")
private String data;
@Column(name = "need_ack", columnDefinition = "TINYINT")
private Boolean needAck = false;
@OneToMany(mappedBy = "log", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private Set<AlarmLogAck> acks = new HashSet<>();
@Column(name = "code", nullable = false)
private int code = 0;
@Column(name = "subtype", length = SUBTYPE_MAX_LENGTH)
private String subtype;
@Column(name = "subtype_id")
private Integer subtypeId;
@Column(name = "subtype_uuid", nullable = true, columnDefinition = "CHAR")
private String subtypeUuid;
AlarmLogAck:
@Entity
@Table(name = "z_alarm_log_ack")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AlarmLogAck extends AbstractLongIdEntity {
private static final int MESSAGE_MAX_LENGTH = 200;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "zipato_id")
private Zipato zipato;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "log_id")
private AlarmLog log;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
private User user;
@Column(name = "show_date", nullable = false, columnDefinition = "DATETIME")
private Date showDate;
@Column(name = "ack_date", nullable = true, columnDefinition = "DATETIME")
private Date ackDate;
@Column(name = "message", length = MESSAGE_MAX_LENGTH, nullable = true)
private String message;
AlarmLogRepository:
@Transactional(readOnly = true)
public interface AlarmLogRepository extends JpaRepository<AlarmLog, Long>, JpaSpecificationExecutor<AlarmLog> {
@Query("FROM AlarmLog " + //
"WHERE zipato=:zipato " + //
" AND alarmId=:alarmId " + //
" AND subtype='ZONE' " + //
" AND subtypeUuid=:zone " + //
" AND timestamp BETWEEN :start AND :end" + //
" AND needAck=true " + //
" AND size(AlarmLog.acks)=0")
List<AlarmLog> findAlarmLogsByZoneAndDatesAndNeedsAck(@Param("zipato") Zipato p_zipato,
@Param("alarmId") Integer p_alarmId,
@Param("zone") String p_zone,
@Param("start") Date p_start,
@Param("end") Date p_end);
我尝试用谷歌搜索这个错误,但找不到 plural-attribute
无法识别的确切组合。我还尝试调试到一定程度,发现此 Set
未被识别为 Collection 类型,或者更准确地说 acks Set
不在列表中,因此无法被识别为plural-attribute
.
我不知道如何解决这个问题...
有什么想法吗?
对于该查询,您应该为实体设置标识符 AlarmLog
并按以下方式在 where 条件中使用该标识符:
...
@Query("FROM AlarmLog al " +
"WHERE zipato=:zipato " +
" AND alarmId=:alarmId " +
" AND subtype='ZONE' " +
" AND subtypeUuid=:zone " +
" AND timestamp BETWEEN :start AND :end" +
" AND needAck=true " +
" AND size(al.acks)=0")
...