Related
i have this four classes:
#Entity
#Table(name = "products")
public class Product extends RegionDiscriminator {
#Column(nullable = false, name = "product_id")
private Long productId;
#Column(nullable = false, name = "name")
private String name;
#Column(nullable = false, name = "category_id")
private Long categoryId;
#Column(nullable = false, name = "unit")
private String unit;
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<SkuGroup> skuGroups = new ArrayList<>();
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Tax> taxes = new ArrayList<>();
#Column(nullable = false, name = "active")
private boolean active;
}
#Entity
#Table(name = "sku_groups")
public class SkuGroup extends RegionDiscriminator {
#Column(nullable = false, name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "product_id")
private Product product;
#OneToMany(mappedBy = "skuGroup", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Sku> skus = new ArrayList<>();
#OneToMany(mappedBy = "skuGroup", cascade = CascadeType.ALL, orphanRemoval = true)
#OrderBy("period DESC")
private List<Cluster> clusters = new ArrayList<>();
}
#Entity
#Table(name = "skus")
public class Sku extends GrowthEntity {
#Column(nullable = false, name = "sku_id")
private Long skuId;
#Column(nullable = false, name = "name")
private String name;
#Column(nullable = false, name = "min_weight_unit")
private BigDecimal minWeightUnit;
#Column(name = "upc")
private String upc;
#OneToMany(mappedBy = "sku", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Tier> tiers = new ArrayList<>();
#OneToMany(mappedBy = "sku", cascade = CascadeType.ALL, orphanRemoval = true)
#Size(max = 10)
#OrderBy("creationTimestamp DESC")
private List<Price> prices = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "sku_group_id")
private SkuGroup skuGroup;
#OneToMany(mappedBy = "sku", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Discount> discounts = new ArrayList<>();
#Column(nullable = false, name = "active")
private boolean active;
#OneToOne(mappedBy = "sku")
private SkuCost cost;
#OneToOne(mappedBy = "sku")
private SkuBenchmark benchmark;
#OneToMany(mappedBy = "sku", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<PricingProcessDetail> pricingProcessDetails;
}
#Entity
#Table(name = "prices")
public class Price extends GrowthEntity {
#Column(nullable = false, name = "retail_price")
private BigDecimal retailPrice;
#Column(nullable = false, name = "tax_price")
private BigDecimal taxPrice;
#Column(nullable = false, name = "pricing_price")
private BigDecimal pricingPrice;
#Column(nullable = false, name = "sale_price")
private BigDecimal salePrice;
#ManyToOne
#JoinColumn(name = "sku_id")
private Sku sku;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(name = "price_discount",
joinColumns = #JoinColumn(name = "price_id"),
inverseJoinColumns = #JoinColumn(name = "discount_id")
)
private List<Discount> discounts = new ArrayList<>();
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(name = "price_tax",
joinColumns = #JoinColumn(name = "price_id"),
inverseJoinColumns = #JoinColumn(name = "tax_id")
)
private List<Tax> taxes = new ArrayList<>();
#OneToMany(mappedBy = "price", cascade = CascadeType.ALL, orphanRemoval = true)
private List<PriceTier> tiers = new ArrayList<>();
}
This are the methods executed by my service:
#Transactional
public Product updateProduct(final ProductDTO productDTO) {
final Product product = productDao.findByProductId(productDTO.getProductId())
.orElseThrow(() -> new GrowthNotFoundException(format("Product with id %s not found",
productDTO.getProductId())));
product.update(productDTO);
return save(product);
}
public Product update(final ProductDTO productDTO) {
categoryId = productDTO.getCategory() != null ? productDTO.getCategory().getId() : null;
name = productDTO.getName();
unit = productDTO.getUnit();
active = productDTO.isActive();
this.updateTaxes(productDTO);
this.updateSkuGroups(productDTO);
return this;
}
private void updateTaxes(final ProductDTO productDTO) {
List<Tax> newTaxes = buildTaxes(productDTO);
List<Tax> currentTaxes = new ArrayList<>(taxes);
if (!currentTaxes.equals(newTaxes)) {
taxes.clear();
taxes.addAll(newTaxes);
}
}
private void updateSkuGroups(final ProductDTO productDTO) {
Map<Long, Sku> skusMap = allSkus().stream()
.collect(Collectors.toMap(Sku::getSkuId, Function.identity()));
Map<String, List<SkuDTO>> newSkuGroups = ProductDTO.groupSkus(productDTO.getSkus());
Map<String, SkuGroup> currentSkuGroups = skuGroups.stream().collect(
Collectors.toMap(SkuGroup::getName, skuGroup -> skuGroup));
newSkuGroups.forEach((group, skus) -> {
if (currentSkuGroups.containsKey(group)) {
SkuGroup skuGroup = currentSkuGroups.get(group);
skuGroup.update(
skus.stream().map(skuDTO -> createOrUpdateSku(skusMap, skuDTO, skuGroup))
.collect(Collectors.toList()));
} else {
SkuGroup skuGroup = SkuGroup.create(group, this);
skuGroup.update(
skus.stream().map(skuDTO -> createOrUpdateSku(skusMap, skuDTO, skuGroup))
.collect(Collectors.toList()));
skuGroups.add(skuGroup);
}
});
currentSkuGroups.forEach((group, skuGroup) -> {
if (!newSkuGroups.containsKey(group)) {
skuGroups.remove(skuGroup);
}
});
}
private Sku createOrUpdateSku(Map<Long, Sku> skusMap, SkuDTO skuDTO, SkuGroup skuGroup) {
if (skusMap.containsKey(skuDTO.getId())) {
return skusMap.get(skuDTO.getId()).update(skuDTO, skuGroup);
} else {
return Sku.create(skuDTO, skuGroup);
}
}
public static Sku create(final SkuDTO skuDTO, final SkuGroup skuGroup) {
Sku sku = Sku.builder()
.withSkuId(skuDTO.getId())
.withMinWeightUnit(skuDTO.getMinWeightUnit())
.withUpc(skuDTO.getUpc())
.withName(skuDTO.getName())
.withSkuGroup(skuGroup)
.isActive(skuDTO.isActive())
.build();
sku.createTiers(skuDTO.getTiers(), skuDTO.getPrice());
sku.createPrice(skuDTO);
return sku;
}
public Sku update(final SkuDTO skuDTO, final SkuGroup theSkuGroup) {
minWeightUnit = skuDTO.getMinWeightUnit();
upc = skuDTO.getUpc();
name = skuDTO.getName();
skuGroup = theSkuGroup;
active = skuDTO.isActive();
this.updateTiers(skuDTO.getTiers(), skuDTO.getPrice());
this.updatePriceFromRetailPrice(skuDTO.getPrice());
return this;
}
This is an example of ProductDTO:
{
"productId": 16825,
"name": "Producto prueba pricing 30",
"category": {
"id": 100515,
"name": "Categoria prueba 13"
},
"iva": null,
"unit": "UNID",
"activeStartDate": "2022-11-22 12:18:08",
"activeEndDate": "2022-11-22 12:18:08",
"skus": [
{
"id": 22937,
"upc": "BOG-FRU1-CAT4252-16825:17883:17882:22937",
"name": "Producto prueba pricing 30 (Caja x 12) - 30 unidades 160g",
"owner": {
"id": 1,
"name": "Frubana"
},
"price": 999,
"stepUnit": 1,
"minWeightUnit": 1,
"conversion": {
"conversionTypeX": "UNID",
"conversionValueX": null,
"conversionTypeY": null,
"conversionValueY": null
},
"slot": false,
"cooled": false,
"activeStartDate": "2022-10-19 12:17:04",
"activeEndDate": "2022-10-19 12:17:04",
"tiers": null,
"group": "(Caja x 24)",
"active": true
},
{
"id": 22938,
"upc": "BOG-FRU1-CAT4252-16825:17885:17884:22938",
"name": "Producto prueba pricing 30 (Caja x 24) - 30 unidades de 150g",
"owner": {
"id": 1,
"name": "Frubana"
},
"price": 888,
"stepUnit": 1,
"minWeightUnit": 1,
"conversion": {
"conversionTypeX": "UNID",
"conversionValueX": null,
"conversionTypeY": null,
"conversionValueY": null
},
"slot": false,
"cooled": false,
"activeStartDate": "2022-10-19 12:17:04",
"activeEndDate": "2022-10-19 12:17:04",
"tiers": null,
"group": "(Caja x 12)",
"active": true
},
{
"id": 22939,
"upc": "BOG-FRU1-CAT4252-16825:17887:17886:22939",
"name": "Producto prueba pricing 30 (Caja x 24) - 30 unidades de 160g",
"owner": {
"id": 1,
"name": "Frubana"
},
"price": 777,
"stepUnit": 1,
"minWeightUnit": 2,
"conversion": {
"conversionTypeX": "UNID",
"conversionValueX": null,
"conversionTypeY": null,
"conversionValueY": null
},
"slot": false,
"cooled": false,
"activeStartDate": "2022-10-19 12:17:04",
"activeEndDate": "2022-10-19 12:17:04",
"tiers": null,
"group": "(Caja x 24)",
"active": true
}
],
"image": "/cmsstatic/products/sku_sin_imagen.png",
"active": true
}
My goal is to assign the SKUs to their respective SKU Groups based on the name, eliminating the groups that are left empty and creating the new ones that are necessary.
The code works for the first part, but fails when the reassignment needs the creation of a new group.
ERROR: null value in column "sku_id" violates not-null constraint
JobName id is primary and is mapped with JobStatus jobid
public class JobName implements Serializable {
private static final long serialVersionUID = 1;
#Id
#Column(name = "ID")
private Integer id;
#Column(name = "NAME")
private String name;
#Column(name = "SCHEDULEDTIME")
private String scheduledTime;
#Column(name = "THRESHOLD")
private Integer threshold;
#Column(name = "TYPE")
private String type;
#OneToMany(mappedBy = "jobName", fetch = FetchType.EAGER)
private List<JobStatus> jobStatus;
}
public class JobStatus implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
private Integer statusId;
#Column(name = "STARTDATE")
private Timestamp startDate;
#Column(name = "ENDDATE")
private Timestamp endDate;
#Column(name = "STATUS")
private String status;
#Column(name = "REMARKS")
private String remarks;
#ManyToOne
#JoinColumn(name = "JOBID")
#JsonIgnore
private JobName jobName;
}
#Repository
public interface JobRepository extends JpaRepository<JobName, Integer> {
#Query("select j from JobName j join j.jobStatus s where s.startDate> :fromDate")
public List<JobName> findJobNameBylastTime(#Param("fromDate") Timestamp fromDate);
}
I want to fetch all records from jobstatus table where startDate is greater than the date sent.
I want response in below json format, I am getting jobName list size correct based on date passed but all jobStatus records present in DB are fetched.
{
"id":"",
"jobName": "",
"scheduledTime": "",
"threshold": "",
"type": "",
"jobStatus": [
{
"statusId":"",
"startDate": "",
"endDate": "",
"status": "",
"remarks": ""
},
{
"statusId":"",
"startDate": "",
"endDate": "",
"status": "",
"remarks": ""
}
]
}
]
Worked by adding FETCH in query
#Repository
public interface JobRepository extends JpaRepository<JobName, Integer> {
#Query("select j from JobName j join fetch j.jobStatus s where s.startDate > :fromDate")
public List<JobName> findJobNameBylastTime(#Param("fromDate") Timestamp fromDate);
}
First, it seems like there is an error in your query, it should be s.startDate > :fromDate instead of s.jobStatus
Then, if you want to query JobStatus entites then you should use a JobStatusRepository as this :
#Repository
public interface JobStatusRepository extends JpaRepository<JobStatus, Integer> {
public List<JobName> findJobNameByCreationDateGreaterThan(Timestamp fromDate);
}
You shouldn't need a query as the method name is enough, you might want to add a ...Distinct... to avoid duplicates.
I'm building a RESTful API GET method with Spring Boot to get return of a Bill entity as JSON from database. The return is not expected as it has many duplicated values and a StackOverFlowError.
[{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":
//continues for eternity
Hibernate log:
Hibernate:
select
bill0_.bill_id as bill_id1_0_,
bill0_.date as date2_0_,
bill0_.time as time3_0_,
bill0_.total as total4_0_
from
bill bill0_
Hibernate:
select
billdetail0_.bill_id as bill_id1_1_0_,
billdetail0_.menu_item_id as menu_ite2_1_0_,
billdetail0_.bill_id as bill_id1_1_1_,
billdetail0_.menu_item_id as menu_ite2_1_1_,
billdetail0_.quantity as quantity3_1_1_,
billdetail0_.subtotal as subtotal4_1_1_,
menuitem1_.menu_item_id as menu_ite1_2_2_,
menuitem1_.description as descript2_2_2_,
menuitem1_.img_url as img_url3_2_2_,
menuitem1_.name as name4_2_2_,
menuitem1_.price as price5_2_2_,
menuitem1_.status as status6_2_2_,
menuitem1_.type as type7_2_2_
from
bill_detail billdetail0_
inner join
menu_item menuitem1_
on billdetail0_.menu_item_id=menuitem1_.menu_item_id
where
billdetail0_.bill_id=?
How can I get a return of a Bill like this:
{
"billId": 1,
"date": 2022-05-20,
"time": 16:48:06,
"total": 330000,
"billDetails": [
{
"menuItem": {
"id": 1,
"name": Rice,
// other attributes of MenuItem
},
"quantity": 2
"subtotal": 90000
},
{
"menuItem": {
"id": 2
"name": Wine
// other attributes of MenuItem
},
"quantity": 4
"subtotal": 240000
}
]
}
This is my classes and related functions
Class Bill
#Entity(name = "bill")
#Table(name = "bill")
public class Bill {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
#Column(name = "bill_id")
private Long id;
private LocalDate date;
private LocalTime time;
private Double total;
#OneToMany(mappedBy = "bill", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();
Class MenuItem
#Entity
#Table(name = "menuItem",
uniqueConstraints = {
#UniqueConstraint(name = "menu_item_name_unique", columnNames = "name")
}
)
public class MenuItem {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
#Column(name = "menu_item_id")
private Long id;
private ItemType type;
private String name;
private String description;
private String imgUrl;
private Double price;
private MenuItemStatus status = MenuItemStatus.ENABLED;
#OneToMany(mappedBy = "menuItem", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();
Class BillDetail
#Entity
#Table(name = "bill_detail")
public class BillDetail {
#EmbeddedId
private BillMenuItemID billMenuItemID = new BillMenuItemID();
#ManyToOne
#MapsId("billId")
#JoinColumn(name = "bill_id")
private Bill bill;
#ManyToOne
#MapsId("menuItemId")
#JoinColumn(name = "menu_item_id")
private MenuItem menuItem;
#Column
private Long quantity;
#Column
private Double subtotal;
GET method
#GetMapping
public List<Bill> getMenuItems() {
return billService.getBills();
}
public List<Bill> getBills() {
return billRepository.findAll();
}
public interface BillRepository extends JpaRepository<Bill, Long> {
}
Database
database
In the class MenuItem you should add the annotation #JsonIgnore to prevent an infinite loop in the JSON format returned; a bill has a BillDetails , a BillDetails has a MenuItem , a MenuItem Has a BillDetails , every BillDetail has a List of MenuItem ...
#Entity
#Table(name = "menuItem",
uniqueConstraints = {
#UniqueConstraint(name = "menu_item_name_unique", columnNames = "name")
}
)
public class MenuItem {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
#Column(name = "menu_item_id")
private Long id;
private ItemType type;
private String name;
private String description;
private String imgUrl;
private Double price;
private MenuItemStatus status = MenuItemStatus.ENABLED;
// ADD JSON IGNORE ANNOTATION HERE :
#JsonIgnore
#OneToMany(mappedBy = "menuItem", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();
I am using spring boot and jpa with restful api. when i am trying to get list of event then this type of error occurs - org.hibernate.QueryException: illegal attempt to dereference collection [events0_.id.typesOfEvents] with element property reference [type_id]
I am passing List Object to constructor as args into jpa custom query but that query will not execute it will fire error.
Event is Main entity inside this entity i have taken List of typeOfEvents with using ManyToMany relation and that two table of Id is stored into third table.
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
#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.Error
org.hibernate.QueryException: illegal attempt to dereference collection [events0_.id.typesOfEvents] with element property reference [type_id]
You reference type_id from list which its not allowed here, because query expression referring type_id to list, not to entity itself. So only replace this LEFT JOIN e.typesOfEvents.type_id t with LEFT JOIN e.typesOfEvents t and it would be work fine. And it would reference variable t to element from list(Relation).
#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);
My Query with changes into 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);
output :
{
"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
}
]
}
]
}
I'm using hibernate JPA annotations, and as for repositories I'm using Spring JPA
i have the following two entities:
#Entity
#Table(name = "idn_organization")
#Audited
public class Organization extends UuidBasedEntity {
#Column(name = "full_name", length = 64, nullable = false)
private String fullName;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
#JoinTable(
name = "idn_organization_address",
joinColumns = #JoinColumn(name = "organization_id"),
inverseJoinColumns = #JoinColumn(name = "address_id")
)
private Set<Address> addresses;
#Column(name = "phone_number", length = 12, nullable = true)
private String phoneNo;
#Column(name = "registered_date", nullable = true)
private Date registeredDate;
#Column(name = "social_security", length = 9, nullable = true)
private String socialSecurity;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public Set<Address> getAddresses() {
return addresses != null ? addresses : new HashSet<Address>();
}
public void setAddresses(Set<Address> addresses) {
if (this.addresses == null)
this.addresses = new HashSet<>();
this.addresses.clear();
if (addresses != null)
this.addresses.addAll(addresses);
}
And:
#Entity
#Table(name = "cmn_address")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#Audited
public class Address extends AutoIdBasedEntity {
#Valid
#NotNull(message = "{address.type.notNull}")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "type_code")
#ForeignKey(name = "FK_address_address_type")
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
private AddressType type;
#NotNull(message = "{address.line1.notNull}")
#Column(name = "address_line_1", length = 256, nullable = true)
private String addressLine1;
#Column(name = "address_line_2", length = 128, nullable = true)
private String addressLine2;
#Column(name = "address_line_3", length = 128, nullable = true)
private String addressLine3;
#Valid
#NotNull(message = "{address.town.notNull}")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "city_id")
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
private Town city;
#NotNull(message = "{address.state.notNull}")
#Size(min = 2, max = 2, message = "{address.state.notEmpty}")
#Column(name = "state_code")
private String state;
//#NotNull(message = "{address.zip.notNull}")
// TODO Not all DTOP Results match
// #Pattern(regexp = "\\d{5}(-\\d{4})?", message = "{address.zip.notValid}")
#Column(name = "postal_code", length = 32, nullable = true)
private String postalCode;
#Valid
#NotNull(message = "{address.country.notNull}")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "country_code")
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
private Country country;
As mentioned my repository is:
public interface OrganizationRepository extends JpaRepository<Organization, String>, JpaSpecificationExecutor<Organization> {
}
The problem I'm having is specifically with the method save in my service:
#Service("identityService")
#Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public class IdentityServiceImpl implements IdentityService {
private static Logger logger = LoggerFactory.getLogger(IdentityServiceImpl.class);
#Autowired
private OrganizationRepository organizationRepository;
#Override
public void persistOrganization(Organization organization) {
organizationRepository.save(organization);
if (logger.isDebugEnabled()) {
logger.debug("Organization [" +
organization.getUuid() + " - " +
organization.getFullName() + "] created or updated.");
}
}
}
Whenever I call my save method the organization is persisted and so is the address in their respective tables... but the join table entry is not! Therefore, I obtain a new organization, a new address, but there's no link between them. So what am I doing wrong here? It obviously also happens when I try to edit the organization somehow.
The problem was in my service as I had the annotation:
#Transactional(readOnly = true, propagation = Propagation.REQUIRED)
and because I was managing transactions through web flow, they never commited. So I added #Transactional to the persist methods and that fixed it. You can also just remove the readOnly = true part, but I didn't because there were fetch methods that I didn't want to be exposed.