【问题标题】:org.hibernate.QueryException: illegal attempt to dereference collection [events0_.id.typesOfEvents] with element property reference [type_id]org.hibernate.QueryException:非法尝试使用元素属性引用 [type_id] 取消引用集合 [events0_.id.typesOfEvents]
【发布时间】:2020-05-29 12:31:38
【问题描述】:

我正在使用带有 restful api 的 spring boot 和 jpa。当我试图获取事件列表时,会发生这种类型的错误 - org.hibernate.QueryException:非法尝试使用元素属性引用 [type_id] 取消引用集合 [events0_.id.typesOfEvents]

我将 List 对象作为 args 传递给构造函数到 jpa 自定义查询中,但该查询不会执行它会引发错误。

事件是该实体中的主要实体,我使用 ManyToMany 关系获取了 typeOfEvents 列表,并且将两个 Id 表存储到第三个表中。

1.Event.java

@Builder
@ToString
@Entity
@Table(name = "events")
public @Data
class Events implements Comparable<Events> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long id;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "site_id")
    private Sites sites;

    @Column
    private boolean multipleDays;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(name = "events_types",
            joinColumns = @JoinColumn(name = "e_id"),
            inverseJoinColumns = @JoinColumn(name = "t_id", unique = false))
    private List<TypesOfEvents> typesOfEvents = new ArrayList<TypesOfEvents>(Arrays.asList());

    @ManyToMany(cascade = CascadeType.DETACH)
    @JoinTable(name = "events_format",
            joinColumns = @JoinColumn(name = "e_id"),
            inverseJoinColumns = @JoinColumn(name = "fs_id", unique = false))
    private List<FormatStructure> formatStructure = new ArrayList<>();

    @Column
    private String startDate;

    @Column
    private String startTime;

    @Column
    private String endDate;

    @Column
    private String endTime;

    @Column
    private String eventName;

    @Column
    private String subTitle;

    @Column
    private String description;

    @Column
    private String location;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "city_id")
    private City city;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "venue_one_off_option_id")
    private VenueOneOffOptions venueOneOffOptions;

    @Column
    private double fee;

    @Column
    private boolean paid;

    @Column
    private String eventImg;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "event_passport_option_id")
    private EventPassportOptions eventPassportOptions;

    @Column
    private int passportTickets;

    @Column
    private int remainingTickets;

    @Column
    private boolean passport;

    @Column
    private int passportDiscountPercent;

    @Column
    private String promoCode;

    @Column
    private String siteUrl;

    @Column
    private String ticketPurchaseSite;

    @Column
    private String videoUrl;


    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "primary_contact_member_id")
    private Members primary_contact_member_id;


    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "created_member_id")
    private Members created_member_id;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "group_id")
    private Groups groups;

    @Column
    private String expectedAttendance;

    @Column
    private boolean myFavourite;

    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "eventStatusId")
    private EventStatus eventStatus;

    @Column
    private boolean purchasedPromotionalEmails;

    @Column
    private boolean featured;

    @ManyToMany(cascade = CascadeType.DETACH)
    @JoinTable(name = "events_audience_types",
            joinColumns = @JoinColumn(name = "e_id"),
            inverseJoinColumns = @JoinColumn(name = "at_id", unique = false))
    private List<AudienceTypes> audienceTypes = new ArrayList<>();

    @ManyToMany(cascade = CascadeType.DETACH)
    @JoinTable(name = "events_food_options",
            joinColumns = @JoinColumn(name = "e_id"),
            inverseJoinColumns = @JoinColumn(name = "fo_id", unique = false))
    private List<FoodOptions> foodOptions = new ArrayList<>();

    public Events() {
    }


    @Override
    public int compareTo(Events o) {
        return (int) (this.id - o.id);
    }
}

2.EventDTO.java

@ToString
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.CUSTOM)
public @Data
class TestDTO implements Comparable<TestDTO>{

    private Long id;

    private boolean multipleDays;

    private List<TypesOfEvents> eventType = new ArrayList<>(Arrays.asList());

    private String startDate;

    private String startTime;

    private String endDate;

    private String endTime;

    private String eventName;

    private String subTitle;

    private String location;

    private String city;

    private double fee;

    private boolean paid;

    private String eventImg;

    private Long passportOption;

    private int passportTickets;

    private int remainingTickets;

    private boolean passport;

    private String promoCode;

    private String expectedAttendance;

    private boolean myFavourite;

    private String eventStatus;

    private boolean featured;

    public TestDTO(Long id, boolean multipleDays, List<TypesOfEvents> eventType, String startDate, String startTime, String endDate, String endTime, String eventName, String subTitle, String location, String city, double fee, boolean paid, String eventImg, Long passportOption, int passportTickets, int remainingTickets, boolean passport, String promoCode, String expectedAttendance, boolean myFavourite, String eventStatus, boolean featured) {
        this.id = id;
        this.multipleDays = multipleDays;
        this.eventType = eventType;
        this.startDate = startDate;
        this.startTime = startTime;
        this.endDate = endDate;
        this.endTime = endTime;
        this.eventName = eventName;
        this.subTitle = subTitle;
        this.location = location;
        this.city = city;
        this.fee = fee;
        this.paid = paid;
        this.eventImg = eventImg;
        this.passportOption = passportOption;
        this.passportTickets = passportTickets;
        this.remainingTickets = remainingTickets;
        this.passport = passport;
        this.promoCode = promoCode;
        this.expectedAttendance = expectedAttendance;
        this.myFavourite = myFavourite;
        this.eventStatus = eventStatus;
        this.featured = featured;
    }
}   

3.查询

@Query("SELECT new com.test.responseDTO.TestDTO(e.id, e.multipleDays, e.typesOfEvents, e.startDate, e.startTime, e.endDate, e.endTime, e.eventName, e.subTitle, e.location, c.name, e.fee, e.paid, e.eventImg, p.event_passport_option_id, e.passportTickets, e.remainingTickets, e.passport, e.promoCode, e.expectedAttendance, e.myFavourite, s.status, e.featured)" +
            " from Events e LEFT JOIN e.typesOfEvents.type_id t JOIN e.city c JOIN e.eventPassportOptions p JOIN e.eventStatus s WHERE e.startDate BETWEEN :startDate AND :endDate AND e.endDate BETWEEN :startDate AND :endDate ORDER BY e.startDate, e.id ASC")
    List<TestDTO> findAllListOfEventsWithoutEventTypeIdWithOnlyTwoDateTest1(String startDate, String endDate);

4.错误

org.hibernate.QueryException: illegal attempt to dereference collection [events0_.id.typesOfEvents] with element property reference [type_id]

【问题讨论】:

  • 你不能在构造函数表达式的构造函数中使用集合。
  • @Simon Martinelli 那么如何解决这个问题请帮助我。因为我想要带有对象列表的自定义字段
  • 为什么需要 typesOfEvents?
  • 在前端显示某些字段所必需的

标签: java spring-boot jpa


【解决方案1】:

您从列表中引用 type_id 此处不允许,因为查询表达式将 type_id 引用到列表,而不是实体本身。所以只需用LEFT JOIN e.typesOfEvents t 替换这个LEFT JOIN e.typesOfEvents.type_id t 就可以了。它会将变量t 引用到列表(关系)中的元素。

    @Query("SELECT new com.test.responseDTO.TestDTO(e.id, e.multipleDays, e.typesOfEvents, e.startDate, e.startTime, e.endDate, e.endTime, e.eventName, e.subTitle, e.location, c.name, e.fee, e.paid, e.eventImg, p.event_passport_option_id, e.passportTickets, e.remainingTickets, e.passport, e.promoCode, e.expectedAttendance, e.myFavourite, s.status, e.featured)" +
            " from Events e LEFT JOIN e.typesOfEvents t /*this fixed*/ JOIN e.city c JOIN e.eventPassportOptions p JOIN e.eventStatus s WHERE e.startDate BETWEEN :startDate AND :endDate AND e.endDate BETWEEN :startDate AND :endDate ORDER BY e.startDate, e.id ASC")
    List<TestDTO> findAllListOfEventsWithoutEventTypeIdWithOnlyTwoDateTest1(String startDate, String endDate);

我的查询更改为 TestDTO

    @Query("SELECT new com.techavidus.networkingPhoniex.responseDTO.TestDTO(e.id, e.multipleDays, t, e.startDate, e.startTime, e.endDate, e.endTime, e.eventName, e.subTitle, e.location, c.name, e.fee, e.paid, e.eventImg, p.event_passport_option_id, e.passportTickets, e.remainingTickets, e.passport, e.promoCode, e.expectedAttendance, e.myFavourite, s.status, e.featured)" +
            " from Events e LEFT JOIN e.typesOfEvents t JOIN e.city c JOIN e.eventPassportOptions p JOIN e.eventStatus s WHERE e.startDate BETWEEN :startDate AND :endDate AND e.endDate BETWEEN :startDate AND :endDate ORDER BY e.startDate, e.id ASC")
    List<TestDTO> findAllListOfEventsWithoutEventTypeIdWithOnlyTwoDateTest1(String startDate, String endDate);

输出:

{
  "success": true,
  "message": "Record's find successfully.",
  "data": [
    {
      "date": "2020/05/28",
      "count": 2,
      "events": [
        {
          "id": 1,
          "multipleDays": true,
          "eventType": {
            "type_id": 1,
            "type": "Musician1",
            "paid_listing": false,
            "color": "Black",
            "_enabled": true
          },
          "startDate": "2020/05/28",
          "startTime": "10:12:15",
          "endDate": "2020/05/30",
          "endTime": "20:18:25",
          "eventName": "Test",
          "subTitle": "Testing demo",
          "location": "string",
          "city": "Bhuj",
          "fee": 49,
          "paid": false,
          "eventImg": "Imgage url",
          "passportOption": 1,
          "passportTickets": 0,
          "remainingTickets": 0,
          "passport": false,
          "promoCode": "TEST123",
          "expectedAttendance": "1500",
          "myFavourite": false,
          "eventStatus": "Pending Approval",
          "featured": false
        },
        {
          "id": 1,
          "multipleDays": true,
          "eventType": {
            "type_id": 2,
            "type": "Personal Growth",
            "paid_listing": true,
            "color": "Black",
            "_enabled": true
          },
          "startDate": "2020/05/28",
          "startTime": "10:12:15",
          "endDate": "2020/05/30",
          "endTime": "20:18:25",
          "eventName": "Test",
          "subTitle": "Testing demo",
          "location": "string",
          "city": "Bhuj",
          "fee": 49,
          "paid": false,
          "eventImg": "Imgage url",
          "passportOption": 1,
          "passportTickets": 0,
          "remainingTickets": 0,
          "passport": false,
          "promoCode": "TEST123",
          "expectedAttendance": "1500",
          "myFavourite": false,
          "eventStatus": "Pending Approval",
          "featured": false
        }
      ]
    }
  ]
}

【讨论】:

  • 我已按照您的建议尝试过,但出现错误----无法在类上找到适当的构造函数
  • /*这个固定的*/ - 这个地方我能做什么?
  • 确保TestDTO上的构造函数有效
  • 但我想提出一些建议(如果您允许),存储库应该按原样检索实体。不要将其转换为 DTO 或其他任何东西,您应该有一个映射器类可以将您的实体映射到 dto。
  • 我已经更新了我的代码。但仍然显示多次相同的 id 我可以合并它吗?
猜你喜欢
  • 2020-04-17
  • 2014-09-05
  • 2015-11-27
  • 2015-12-05
  • 1970-01-01
  • 2011-09-18
  • 2012-10-17
  • 1970-01-01
  • 2011-09-13
相关资源
最近更新 更多