Cannot apply where condition clause in JPA query - java

I wrote a Query in my ProductRepository as below
#Query(value = "select p from Product p where p.code = :code")
Product findByCode(#Param("code")String code);
it's obviously that I just want the query return 1 Product, but some how when I call the API it always return a list of all my products.
this is the generated query I get from the log
Hibernate: select product0_.code as code1_4_, product0_.name as name2_4_, product0_.price as price3_4_, product0_.unit as unit4_4_ from product product0_
I cannot see the WHERE condition clause that I wrote
This is my Product class:
package com.example.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.List;
import java.util.Objects;
#Entity
public class Product {
#Id
private String code;
private String name;
private Float price;
private String unit;
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, mappedBy = "product", cascade
=CascadeType.ALL)
private List<OrderLine> orderLines;
public Product(String code, String name, float price, String unit) {
this.code = code;
this.name = name;
this.price = price;
this.unit = unit;
}
public Product(String code, float price, String unit) {
this.code = code;
this.price = price;
this.unit = unit;
}
public Product(String code) {
this.code = code;
this.price = Float.valueOf(0);
}
public Product(String code, String unit) {
this.code = code;
this.unit = unit;
this.price = Float.valueOf(0);
}
public Product() {}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
#Override
public String toString() {
return "Product{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
", price=" + price +
", unit='" + unit + '\'' +
'}';
}
public List<OrderLine> getOrderLines() {
return orderLines;
}
public void setOrderLines(List<OrderLine> orderLines) {
this.orderLines = orderLines;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Product)) return false;
Product product = (Product) o;
return this.getCode().equals(product.getCode());
}
#Override
public int hashCode() {
return Objects.hash(getCode());
}}
My controller
#RestController
#RequestMapping("/products")
public class ProductController {
#Autowired
ProductRepo productRepo;
#Autowired
StaffRepo staffRepo;
#Autowired
InventoryRepo inventoryRepo;
#GetMapping("/get")
public ResponseEntity getAll(){
List<Product> products = productRepo.findAll();
if(products== null){
return ResponseEntity.status(404).body("Product not found !");
}
return ResponseEntity.ok().body(products);
}
#GetMapping("/get/{code}")
public ResponseEntity getProductByCode(#PathVariable String code){
Product p = productRepo.findByCode(code);
if(p== null){
return ResponseEntity.status(404).body("Product not found !");
}
return ResponseEntity.ok().body(p);
}

Related

Spring Boot: How to make entity reflect database column changes?

I am using spring boot as a backend rest API and connecting to a MySQL database. I created the initial entity and database table that it would map to. I realized one of the columns in my database was named incorrectly and updated its name in the database and updated my entity to reflect the change as well. After doing so, when I send a GET or POST request to my controller endpoints, the values of the returned object do not reflect the changes I made to the entity/database. I have tried changing the spring.jpa.hibernate.ddl-auto property in my applications.properties file to update, create, and create drop, none of which had any success. Here is my entity class, applications.properties file, my controller endpoints, my repository, and 2 images, one of my database table and one of the response from the GET endpoint.
Skin.java
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Entity
#Table(name="skins")
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Skin {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="category")
private String category;
#Column(name="collection")
private String collection;
#Column(name="quality")
private String quality;
#Column(name="wear")
private String wear;
#Column(name="weapon")
private String weapon;
#Column(name="name")
private String name;
#Column(name="price")
private BigDecimal price;
#Column(name="quantity")
private int quantity;
#Column(name="date_bought")
private Date dateBought;
#ManyToOne(cascade= {CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name="trade_id")
private Trade trade;
#Column(name="outcome_sell_price")
private BigDecimal outcomeSellPrice;
#Column(name="date_traded")
private Date dateTraded;
#Column(name="sell_price")
private BigDecimal sellPrice;
#Column(name="date_sold")
private Date dateSold;
public Skin() {
}
public Skin(String category, String collection, String quality, String wear, String weapon, String name,
BigDecimal price, int quantity, Date dateBought, Trade trade, BigDecimal outcomeSellPrice, Date dateTraded,
BigDecimal sellPrice, Date dateSold) {
this.category = category;
this.collection = collection;
this.quality = quality;
this.wear = wear;
this.weapon = weapon;
this.name = name;
this.price = price;
this.quantity = quantity;
this.dateBought = dateBought;
this.trade = trade;
this.outcomeSellPrice = outcomeSellPrice;
this.dateTraded = dateTraded;
this.sellPrice = sellPrice;
this.dateSold = dateSold;
}
public String getWeapon() {
return weapon;
}
public void setWeapon(String weapon) {
this.weapon = weapon;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCollection() {
return collection;
}
public void setCollection(String collection) {
this.collection = collection;
}
public String getWear() {
return wear;
}
public void setWear(String wear) {
this.wear = wear;
}
public String getQuality() {
return quality;
}
public void setQuality(String quality) {
this.quality = quality;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Date getDateBought() {
return dateBought;
}
public void setDateBought(Date dateBought) {
this.dateBought = dateBought;
}
public Trade getTrade() {
return trade;
}
public void setTrade(Trade trade) {
this.trade = trade;
}
public BigDecimal getSellPrice() {
return sellPrice;
}
public void setSellPrice(BigDecimal sellPrice) {
this.sellPrice = sellPrice;
}
public Date getDateTraded() {
return dateTraded;
}
public void setDateTraded(Date dateTraded) {
this.dateTraded = dateTraded;
}
public BigDecimal getSoldAt() {
return outcomeSellPrice;
}
public void setSoldAt(BigDecimal soldAt) {
this.outcomeSellPrice = soldAt;
}
public Date getDateSold() {
return dateSold;
}
public void setDateSold(Date dateSold) {
this.dateSold = dateSold;
}
#Override
public String toString() {
return "Skin [id=" + id + ", category=" + category + ", collection=" + collection + ", quality=" + quality
+ ", wear=" + wear + ", weapon=" + weapon + ", name=" + name + ", price=" + price + ", quantity="
+ quantity + ", dateBought=" + dateBought + ", trade=" + trade + ", outcomeSellPrice=" + outcomeSellPrice
+ ", dateTraded=" + dateTraded + ", sellPrice=" + sellPrice + ", dateSold=" + dateSold + "]";
}
}
Controller Endpoints
#Autowired
SkinRepository sr;
#GetMapping("")
public List<Skin> getSkins() {
return sr.findByTradeIdNullAndDateSoldNull();
}
#PostMapping("")
public Skin insertSkin(#RequestBody Skin skin) {
// need to figure out why this isn't picking up the database changes
return sr.save(skin);
}
SkinRepository.java
#Repository
public interface SkinRepository extends JpaRepository<Skin, Long> {
List<Skin> findByTradeIdNullAndDateSoldNull();
}
application.properties
spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_SCHEMA}?useSSL=false&serverTimezone=UTC
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASS}
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
spring.jpa.hibernate.ddl-auto=update
Database Table
This is the response I get when sending a request to the GET endpoint. The value soldAt is the old name of the column before changing it, it should be outcome_sell_price.
GET endpoint response
Any thoughts on how I can get the response from the endpoints to match the database and entity would be greatly appreciated. Thanks in advance.
The reason why you still get soldAt related names might be because you have the following getter and setters. Remove or update this getter and setters too and see if you still get erroneous responses.
public BigDecimal getSoldAt() {
return outcomeSellPrice;
}
public void setSoldAt(BigDecimal soldAt) {
this.outcomeSellPrice = soldAt;
}

org.springframework.orm.jpa.JpaSystemException: Error accessing field by reflection for persistent property

I am using Spring Boot (v 2.4.0) with Hibernate 5.4.24 and, when trying to get some information from my database, I keep getting this error message:
org.springframework.orm.jpa.JpaSystemException: Error accessing field [private int es.uc3m.orders.model.Shoppingcart.usID] by reflection for persistent property [es.uc3m.orders.model.Shoppingcart#usID] : 1; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private int es.uc3m.orders.model.Shoppingcart.usID] by reflection for persistent property [es.uc3m.orders.model.Shoppingcart#usID] : 1
It is kind of weird for me, because it only happens when I try to access the table Shoppingcart, since I can get informatin from the rest of the tables.
I also used the exact same entities with another project but, insetad of using Spring Boot, persistence was made with EntityManagers and it worked perfectly fine.
These are my entities:
Shoppingcart
#Entity
#NamedQuery(name="Shoppingcart.findAll", query="SELECT s FROM Shoppingcart s")
public class Shoppingcart implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int scID;
private int usID;
//bi-directional many-to-many association to Product
#ManyToMany
#JoinTable(
name="sc_has_product"
, joinColumns={
#JoinColumn(name="scID")
}
, inverseJoinColumns={
#JoinColumn(name="productID")
}
)
private List<Product> products;
//bi-directional one-to-one association to User
#OneToOne(mappedBy="shoppingcart")
private User user;
public Shoppingcart() {
}
public int getScID() {
return this.scID;
}
public void setScID(int scID) {
this.scID = scID;
}
public int getusID() {
return this.usID;
}
public void setusID(int usID) {
this.usID = usID;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isNull() {
return getProducts().isEmpty();
}
User
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String address;
#Column(name="card_n")
private Long cardN;
private String city;
private String country;
private int cvv;
private String email;
private String exp;
private String name;
private String pass;
private String surname1;
private String surname2;
private String typeOfUser;
#Column(name="zip_code")
private int zipCode;
//bi-directional many-to-one association to Order
#OneToMany(mappedBy="user")
private List<Orders> orders;
//bi-directional many-to-one association to Product
#OneToMany(mappedBy="user")
private List<Product> products;
//bi-directional one-to-one association to Shoppingcart
#OneToOne(cascade=CascadeType.REMOVE)
#JoinColumn(name="ID", referencedColumnName="usID", insertable=false, updatable=false)
private Shoppingcart shoppingcart;
public User() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public Long getCardN() {
return this.cardN;
}
public void setCardN(Long cardN) {
this.cardN = cardN;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public int getCvv() {
return this.cvv;
}
public void setCvv(int cvv) {
this.cvv = cvv;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getExp() {
return this.exp;
}
public void setExp(String exp) {
this.exp = exp;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return this.pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getSurname1() {
return this.surname1;
}
public void setSurname1(String surname1) {
this.surname1 = surname1;
}
public String getSurname2() {
return this.surname2;
}
public void setSurname2(String surname2) {
this.surname2 = surname2;
}
public int getZipCode() {
return this.zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
public List<Orders> getOrders() {
return this.orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
public Orders addOrder(Orders order) {
getOrders().add(order);
order.setUser(this);
return order;
}
public Orders removeOrder(Orders order) {
getOrders().remove(order);
order.setUser(null);
return order;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public Product addProduct(Product product) {
getProducts().add(product);
product.setUser(this);
return product;
}
public Product removeProduct(Product product) {
getProducts().remove(product);
product.setUser(null);
return product;
}
public Shoppingcart getShoppingcart() {
return this.shoppingcart;
}
public void setShoppingcart(Shoppingcart shoppingcart) {
this.shoppingcart = shoppingcart;
}
public String getTypeOfUser() {
return typeOfUser;
}
public void setTypeOfUser(String typeOfUser) {
this.typeOfUser = typeOfUser;
}
}
This is the ShoppingcartDAO class:
public interface ShoppingCartDAO extends CrudRepository<Shoppingcart, Integer> {
#Query("SELECT s FROM Shoppingcart s JOIN User u ON u.id = s.usID AND u.id LIKE :id")
Shoppingcart findByUser(#Param("id") int id);
#Query("SELECT s FROM Shoppingcart s")
List<Shoppingcart> findAllShoppingCart();
}
And, finally, this is my ShoppingcartController class:
#RestController
#CrossOrigin
#EnableAutoConfiguration
public class ShoppingCartController {
#Autowired
ShoppingCartDAO scDAO;
#RequestMapping(value = "sc", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> assignShoppingCart(#RequestBody(required = true) Shoppingcart sc) {
try {
scDAO.save(sc);
return new ResponseEntity<Void>(HttpStatus.CREATED);
} catch(Exception e) {
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
}
#RequestMapping(value = "sc", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<?> getEveryShoppingCart() {
try {
List<Shoppingcart> sc = scDAO.findAllShoppingCart();
return new ResponseEntity<List<Shoppingcart>>(sc, (sc != null) ? HttpStatus.OK : HttpStatus.NOT_FOUND);
} catch(Exception e) {
System.out.println(e);
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
}
}
I am really going nuts as I canĀ“t figure out what is going on with my code, so thank you in advance if you help me.
I finally fixed it. For those of you who are wondering how, I deleted the relationships between tables that I had, ending with:
Shoppingcart:
#Entity
public class Shoppingcart implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int scID;
#Column(name = "usID")
private Integer userID;
public Shoppingcart() {
}
public int getScID() {
return this.scID;
}
public void setScID(int scID) {
this.scID = scID;
}
public Integer getUserID() {
return userID;
}
public void setUserID(Integer userID) {
this.userID = userID;
}
Product:
#Entity
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int productID;
private String category;
private String color;
private String description;
private String estadoProducto;
private String fecha;
private int orderID;
private String photo;
private double price;
private int seller;
private String sexo;
private String state = "Disponible";
private String talla;
private String title;
public Product() {
}
public int getProductID() {
return this.productID;
}
public void setProductID(int productID) {
this.productID = productID;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getColor() {
return this.color;
}
public void setColor(String color) {
this.color = color;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEstadoProducto() {
return this.estadoProducto;
}
public void setEstadoProducto(String estadoProducto) {
this.estadoProducto = estadoProducto;
}
public String getFecha() {
return this.fecha;
}
public void setFecha(String fecha) {
this.fecha = fecha;
}
public String getPhoto() {
return this.photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public double getPrice() {
return this.price;
}
public void setPrice(double price) {
this.price = price;
}
public String getSexo() {
return this.sexo;
}
public void setSexo(String sexo) {
this.sexo = sexo;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getTalla() {
return this.talla;
}
public void setTalla(String talla) {
this.talla = talla;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public int getOrderID() {
return orderID;
}
public void setOrderID(int orderID) {
this.orderID = orderID;
}
public int getSeller() {
return seller;
}
public void setSeller(int seller) {
this.seller = seller;
}
With this, everything worked fine, but don't ask me why, because I don't know it.
Your Getters/Setters are wrongly implemented.
Like :
Actual :
public int getusID() {
return this.usID;
}
Expected :
public int getUsID() {
return this.usID;
}
Same with setter

Hibernate: LazyInitializationException: failed to lazily initialize a collection of role

Using Hibernate 3.6.0
I'm having a real hard time understanding hibernate. I keep running into this issue with lazy initialization exception.
I have an Event entity with a one-to-many relationship with RSVP. When a run a test get back a list of events it works. But when I'm making the call in my controller in order to return it as json, I run into this lazy init error.
This is my event class
#Entity
#Table(name = "EVENT")
public class Event implements Serializable {
#SequenceGenerator(name="event", sequenceName="EVENT_PK_SEQ")
#GeneratedValue(generator="event",strategy=GenerationType.SEQUENCE)
#Id
#Column(name = "EVENT_ID")
private int id;
#Column(name = "DATE_TIME")
private Date date;
#Column(name = "EVENT_NAME")
private String name;
#Column(name = "EVENT_PARTICIPANT_LIMIT")
private int limit;
#Column(name = "EVENT_VISIBILITY")
private boolean visibilty;
#Column(name = "EVENT_LOCATION")
private String location;
#Column(name = "EVENT_DESCRIPTION")
private String description;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private User author;
private Date create_date;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private EventType eventType;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
private EventClass eventClass;
#OneToMany(cascade = CascadeType.ALL)
private Set<RSVP> rsvps = new HashSet<RSVP>();
#ManyToMany(mappedBy="event")
private Set<Group> groups = new HashSet<Group>();
public Event(int id, Date date, String name, int limit, boolean visibilty, String location, String description,
User author, Date create_date, EventType eventType, EventClass eventClass) {
super();
this.id = id;
this.date = date;
this.name = name;
this.limit = limit;
this.visibilty = visibilty;
this.location = location;
this.description = description;
this.author = author;
this.create_date = create_date;
this.eventType = eventType;
this.eventClass = eventClass;
}
public Event(){
super();
}
#Override
public String toString() {
return "Event [id=" + id + ", date=" + date + ", name=" + name + ", limit=" + limit + ", visibilty=" + visibilty
+ ", location=" + location + ", description=" + description + ", author=" + author + ", create_date="
+ create_date + ", eventType=" + eventType + ", eventClass=" + eventClass + ", rsvps=" + rsvps
+ ", groups=" + groups + "]";
}
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public boolean isVisibilty() {
return visibilty;
}
public void setVisibilty(boolean visibilty) {
this.visibilty = visibilty;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public EventType getEventType() {
return eventType;
}
public void setEventType(EventType eventType) {
this.eventType = eventType;
}
public EventClass getEventClass() {
return eventClass;
}
public void setEventClass(EventClass eventClass) {
this.eventClass = eventClass;
}
public Set<RSVP> getRsvps() {
return rsvps;
}
public void setRsvps(Set<RSVP> rsvps) {
this.rsvps = rsvps;
}
public Set<Group> getGroups() {
return groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
}
My RSVP
#Entity
#Table(name="RSVP")
public class RSVP {
#Id
#Column(name="RSVP_ID")
#SequenceGenerator(name="rsvp", sequenceName="RSVP_PK_SEQ")
#GeneratedValue(generator="rsvp",strategy=GenerationType.SEQUENCE)
private int rsvpId;
#OneToOne(cascade=CascadeType.REMOVE, fetch= FetchType.EAGER)
#JoinColumn(name="STATUS_ID")
private RSVPStatus status;
#ManyToOne(cascade=CascadeType.REMOVE)
#JoinColumn(name="USER_ID")
private User user;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="EVENT_ID")
private Event event;
public RSVP(int rsvpId, RSVPStatus status, User user, Event event) {
super();
this.rsvpId = rsvpId;
this.status = status;
this.user = user;
this.event = event;
}
public RSVP() {
}
#Override
public String toString() {
return "RSVP [rsvpId=" + rsvpId + ", status=" + status + ", user=" + user + ", event=" + event + "]";
}
public int getRsvpId() {
return rsvpId;
}
public void setRsvpId(int rsvpId) {
this.rsvpId = rsvpId;
}
public RSVPStatus getStatus() {
return status;
}
public void setStatus(RSVPStatus status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
}
MY controller
public class MyController {
private static SessionFactory sf = HibernateUtils.getSessionFactory();
private DataFacade df = new DataFacade(sf);
#RequestMapping(value="home", method=RequestMethod.GET,
consumes= MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<List<Event>> getUserCal(){
DataFacade df = new DataFacade(sf);
List<Event> events= df.getAllEventsByAuthor(1);
for(Event e:events){
System.out.println(e);
}
return new ResponseEntity<List<Event>>(events,HttpStatus.OK);
}
}
Your RSVP collection is fetched lazily. (If you don't specify a fetch type, the default is lazy). You need to change it to eager if you are planning to access it after the Hibernate session is closed:
#OneToMany(cascade = CascadeType.ALL, fetch= FetchType.EAGER)
private Set<RSVP> rsvps = new HashSet<RSVP>();

Problems with One to many relationship Java JPA

I have a problem with my JPA.
Basically my Couriers are created by the program and the customer and parcels are created by user while running. When I try to add a new parcel I add the object to parcel list in Customer and parcel list in Courier. But it crashes when tries to add to Courier parcel list. I create a courier object before calling my menu in the main class
And it throws the following error:
During synchronization a new object was found through a relationship that was not marked cascade PERSIST: Courier:
Id: 0
Name: null
Vehicle: null.
This is my code:
#Entity
#SequenceGenerator(name="cou_seq", initialValue=1, allocationSize=1)
#SuppressWarnings("SerializableClass")
public class Courier implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="cou_seq")
private int couId;
private String name;
private String vehicle;
#OneToMany(mappedBy = "courier", cascade = CascadeType.PERSIST)
private List<Parcel> plist = new ArrayList<>();
public Courier(){
}
public Courier(String nameIn, String vehicleIn){
name = nameIn;
vehicle = vehicleIn;
}
public void addParcel(Parcel p1){
plist.add(p1);
p1.setCo(this);
}
public int getCouId() {
return couId;
}
public String getName() {
return name;
}
public String getVehicle() {
return vehicle;
}
public void setCouId(int couId) {
this.couId = couId;
}
public void setName(String name) {
this.name = name;
}
public void setVehicle(String vehicle) {
this.vehicle = vehicle;
}
public List<Parcel> getParcel(){
return plist;
}
public void setParcel(List<Parcel> parcels) {
plist = parcels;
}
#Override
public String toString(){
return "Courier: \nId: " + couId + "\nName: " + name + "\nVehicle: " + vehicle;
}
//CUSTOMER CLASS
#Entity
#SequenceGenerator(name="cus_seq", initialValue=1, allocationSize=1)
#SuppressWarnings("SeralizableClass")
public class Customer implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="cus_seq")
private int cusId;
private String login;
private String password;
private String fname;
private String lname;
private String dob;
private String address;
private String phoneNo;
private String email;
#OneToMany(mappedBy = "customer")
private List<Parcel> plist = new ArrayList<>();
public Customer(){
}
public Customer(String loginIn, String passwordIn, String fnameIn, String lnameIn, String dobIn, String addressIn, String phoneNoIn, String emailIn){
login = loginIn;
password = passwordIn;
fname = fnameIn;
lname = lnameIn;
dob = dobIn;
address = addressIn;
phoneNo = phoneNoIn;
email = emailIn;
}
public void addParcel(Parcel p) {
plist.add(p);
p.setC(this);
}
public String getFname() {
return fname;
}
public String getLname() {
return lname;
}
public String getDob() {
return dob;
}
public String getAddress() {
return address;
}
public String getPhoneNo() {
return phoneNo;
}
public String getEmail() {
return email;
}
public void setFname(String fname) {
this.fname = fname;
}
public void setLname(String lname) {
this.lname = lname;
}
public void setDob(String dob) {
this.dob = dob;
}
public void setAddress(String address) {
this.address = address;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public void setEmail(String email) {
this.email = email;
}
public List<Parcel> getParcel(){
return plist;
}
public void setParcel(List<Parcel> parcels) {
plist = parcels;
}
public String toString(){
return "Customer: " + "\nID: " + cusId + "\nLogin: " + login + "\nFirst Name: " + fname + "\nSecond Name: " + lname + "\nDOB: " + dob + "\nAddress: " + address + "\nPhone No: " + phoneNo;
}
}
//PARCEL CLASS
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "type")
#SequenceGenerator(name = "par_seq", initialValue = 1, allocationSize = 1)
#SuppressWarnings("SerializableClass")
public class Parcel {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "par_seq")
private int parId;
private double height;
private double width;
private double length;
private double weight;
private String receiver;
#ManyToOne()
#JoinColumn(name = "cuId")
private Customer customer;
#ManyToOne()
#JoinColumn(name = "coId")
private Courier courier;
private static double price;
public Parcel() {
}
public Parcel(double heightIn, double widthIn, double lengthIn, double weightIn, String receiverIn) {
height = heightIn;
width = widthIn;
length = lengthIn;
weight = weightIn;
receiver = receiverIn;
}
public double getHeight() {
return height;
}
public double getWidth() {
return width;
}
public double getLength() {
return length;
}
public double getWeight() {
return weight;
}
public double getPrice() {
return price;
}
public void setHeight(double height) {
this.height = height;
}
public void setWidth(double width) {
this.width = width;
}
public void setLength(double length) {
this.length = length;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void setPrice(double price) {
this.price = price;
}
public double calcSize(double height, double width, double length) {
return height * width * length;
}
public void setC(Customer c) {
this.customer = c;
}
public Customer getC() {
return customer;
}
public void setCo(Courier c1) {
this.courier = c1;
}
public Courier getCo() {
return courier;
}
#Override
public String toString() {
return "Parcel:\nHeight: " + height + "\nWidth: " + width + "\nLength: " + length + "\nWeight: " + weight;
}
}
//JPA method that adds a new parcel
public Parcel createParcel(double heightAdd, double widthAdd, double lengthAdd, double weightAdd, String receiverAdd,String owner,String type){
int id = findCustomerIdByLogin(owner);
Customer c = em.find(Customer.class, id);
Courier co = new Courier();
em.getTransaction().begin();
if(type.equals("INT")){
System.out.println("Inside here");
InternationalParcel int1 = new InternationalParcel(heightAdd, widthAdd, lengthAdd, weightAdd, receiverAdd);
em.persist(int1);
c.addParcel(int1);
//em.persist(int1);
co.addParcel(int1);
em.getTransaction().commit();
return int1;
} else {
NationalParcel nat1 = new NationalParcel(heightAdd, widthAdd, lengthAdd, weightAdd,receiverAdd);
em.persist(nat1);
c.addParcel(nat1);
em.persist(nat1);
co.addParcel(nat1);
em.getTransaction().commit();
return nat1;
}
}
You are adding your Parcel to a Courier that is not persisted in the Database yet.
You have to Persist your Courier Object as well.
Since you told your Courier Object that it should cascade persist its Parcel objects it should actually be enough to just persist the Courer without persisting each parcel on its own:
Parcel parcel;
Customer c = em.find(Customer.class, id);
Courier co = new Courier();
em.getTransaction().begin();
if(type.equals("INT")){
parcel = new InternationalParcel(heightAdd, widthAdd, lengthAdd, weightAdd, receiverAdd);
} else {
parcel = new NationalParcel(heightAdd, widthAdd, lengthAdd, weightAdd,receiverAdd);
}
co.addParcel(parcel);
em.persist(co); // <- This is what you are currently not doing!
em.persist(parcel); // <- this might not be necessary because of cascade persist
c.addParcel(parcel);
em.getTransaction().commit();
return parcel;

Best way to run a M:N query in hibernate?

Trying to figure out how to use hibernate to call to get a list of the movies for a given genre?!
I tried getting a given genre then using the method from GenreDTO to get the set of movies.
Query hqlQuery = session.createQuery("FROM GenreDTO WHERE genre like :genre");
GenreDTO g = hqlQuery.setParameter("title","%" + term + "%").uniqueResult();
return g.getMovies();
Is there a better way?
CREATE TABLE Movie (
id INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
title VARCHAR(255),
poster VARCHAR(255),
director VARCHAR(255),
actors VARCHAR(255),
synopsis VARCHAR(3000),
release_date TIMESTAMP
);
CREATE TABLE Genre(
id INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
genre VARCHAR(255)
);
CREATE TABLE MovieHasGenre(
movie_id INTEGER REFERENCES Movie (id) NOT NULL,
genre_id INTEGER REFERENCES Genre (id) NOT NULL,
PRIMARY KEY (movie_id, genre_id)
);
package edu.unsw.comp9321.jdbc;
import java.util.HashSet;
import java.util.Set;
public class GenreDTO {
public GenreDTO() {}
public GenreDTO(int id, String genre) {
super();
this.id = id;
this.genre = genre;
}
private int id;
private String genre;
private Set<MovieDTO> movies = new HashSet<MovieDTO>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public Set<MovieDTO> getMovies() {
return movies;
}
public void setMovies(Set<MovieDTO> movies) {
this.movies = movies;
}
}
package edu.unsw.comp9321.jdbc;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.OneToMany;
public class MovieDTO implements Comparable {
private int id;
private String title;
private String poster;
private String director;
private String actors;
private String synopsis;
private String release_date;
private int cinema_id;
private Set<GenreDTO> genres = new HashSet<GenreDTO>();
private Set<ReviewDTO> reviews = new HashSet<ReviewDTO>();
private double rating;
public MovieDTO() {
}
public MovieDTO(int id, String title, String poster, String director,
String actors, String synopsis, String release_date, double rating) {
super();
this.id = id;
this.title = title;
this.poster = poster;
this.director = director;
this.actors = actors;
this.synopsis = synopsis;
this.release_date = release_date;
this.rating = rating;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPoster() {
return poster;
}
public void setPoster(String poster) {
this.poster = poster;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getActors() {
return actors;
}
public void setActors(String actors) {
this.actors = actors;
}
public String getSynopsis() {
return synopsis;
}
public void setSynopsis(String synopsis) {
this.synopsis = synopsis;
}
public String getRelease_date() {
return release_date;
}
public void setRelease_date(String release_date) {
this.release_date = release_date;
}
public Set<GenreDTO> getGenres() {
return genres;
}
public void setGenres(Set<GenreDTO> genres) {
this.genres = genres;
}
public Set<ReviewDTO> getReviews() {
return reviews;
}
public void setReviews(Set<ReviewDTO> reviews) {
this.reviews = reviews;
}
public int getCinema_id() {
return cinema_id;
}
public void setCinema_id(int cinema_id) {
this.cinema_id = cinema_id;
}
public double getRating() {
return rating;
}
public void setRating(double rating) {
this.rating = rating;
}
#Override
public int compareTo(Object o) {
MovieDTO other = (MovieDTO) o;
if (this.rating > other.rating) return -1;
if (this.rating < other.rating) return 1;
return 0;
}
}
Yes. There is a better way. Just use a join:
select m from Movie m join m.genres g where g.genre like :genre
or
select m from Genre g join g.movies m where g.genre like :genre
Note that using a like clause is a bit odd. You should use the ID of the genre to uniquely identify it. And if you only have part of a genre's name, you shouldn't assume only one genre contains this genre part.
Also, a DTO is not an entity, and vice-versa. Don't name an entity GenreDTO or MovieDTO. Name it Genre or Movie.

Categories