Get data from Junction Table with Android Room - java

I am currently building an android app, which displays a Route, which is constructed out of multiple waypoints. I already planned the database schema (chen-notation [possibly invalid "syntax"]):
I tried to recreate the n-m relation with android room, but I can't figure out how I can retrieve the index_of_route attribute of the junction table (route_waypoint).
I want the junction table attribute index_of_route, when I get the Data like so:
#Transaction
#Query("SELECT * FROM POIRoute")
List<RouteWithWaypoints> getRoutes();
inside the POIWaypoint class (maybe as extra attribute), or at least accessible from another class which maybe is implemented like so:
#Embedded
POIWaypoint waypoint;
int indexOfRoute;
Currently I don't get the indexOfRoute attribute from the junction table.
My already created classes:
RouteWithWaypoints:
public class RouteWithWaypoints {
#Embedded
private POIRoute poiRoute;
#Relation(parentColumn = "id",entityColumn = "id",associateBy = #Junction(value = RouteWaypoint.class, parentColumn = "routeId", entityColumn = "waypointId"))
private List<POIWaypoint> waypoints;
public POIRoute getPoiRoute() {
return poiRoute;
}
public void setPoiRoute(POIRoute poiRoute) {
this.poiRoute = poiRoute;
}
public List<POIWaypoint> getWaypoints() {
return waypoints;
}
public void setWaypoints(List<POIWaypoint> waypoints) {
this.waypoints = waypoints;
}
RouteWaypoint:
#Entity(primaryKeys = {"waypointId", "routeId"}, foreignKeys = {
#ForeignKey(entity = POIWaypoint.class, parentColumns = {"id"}, childColumns = {"waypointId"}),
#ForeignKey(entity = POIRoute.class, parentColumns = {"id"}, childColumns = {"routeId"})
})
public class RouteWaypoint {
private int waypointId;
private int routeId;
// I want this attribute inside the POIWaypoint class
#ColumnInfo(name = "index_of_route")
private int indexOfRoute;
public int getWaypointId() {
return waypointId;
}
public void setWaypointId(int waypointId) {
this.waypointId = waypointId;
}
public int getRouteId() {
return routeId;
}
public void setRouteId(int routeId) {
this.routeId = routeId;
}
}
POIRoute:
#Entity
public class POIRoute{
private String name;
private String description;
#PrimaryKey(autoGenerate = true)
private int id;
private boolean user_generated;
private int parentId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isUser_generated() {
return user_generated;
}
public void setUser_generated(boolean user_generated) {
this.user_generated = user_generated;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
}
POIWaypoint (please ignore the position attribute it isn't finished):
#Entity
public class POIWaypoint {
#PrimaryKey(autoGenerate = true)
private long id;
#ColumnInfo(name = "long_description")
private String longDescription;
private String title;
#ColumnInfo(name = "short_description")
private String shortDescription;
// use converter: https://developer.android.com/training/data-storage/room/referencing-data
#Ignore
private GeoPoint position;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public GeoPoint getPosition() {
return position;
}
public void setPosition(GeoPoint position) {
this.position = position;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getLongDescription() {
return longDescription;
}
public void setLongDescription(String longDescription) {
this.longDescription = longDescription;
}

I solved my problem by manage the relation by myself. I changed my RouteDao to an abstract class to insert my own method, which manages part of the junction table by itself:
RouteDao:
private RouteDatabase database;
public RouteDao(RouteDatabase database) {
this.database = database;
}
#Query("Select * from POIRoute")
public abstract List<POIRoute> getRoutes();
#Query("SELECT * FROM POIRoute WHERE id = :id")
public abstract POIRoute getRoute(int id);
#Insert
abstract void insertRouteWithWaypoints(RouteWithWaypoints routeWithWaypoints);
public List<RouteWithWaypoints> getRoutesWithWaypoints() {
List<POIRoute> routes = this.getRoutes();
List<RouteWithWaypoints> routesWithWaypoints = new LinkedList<>();
for (POIRoute r : routes) {
routesWithWaypoints.add(new RouteWithWaypoints(r, database.wayPointDao().getWaypointsFromRoute(r.getId())));
}
return routesWithWaypoints;
}
public RouteWithWaypoints getRouteWithWaypoints(int id) {
POIRoute route = this.getRoute(id);
RouteWithWaypoints routeWithWaypoints = null;
if (route != null) {
routeWithWaypoints = new RouteWithWaypoints(route, database.wayPointDao().getWaypointsFromRoute(route.getId()));
}
return routeWithWaypoints;
}
WayPointDao:
#Query("SELECT * FROM POIWaypoint")
POIWaypoint getWaypoints();
#Query("SELECT * FROM POIWaypoint WHERE id = :id")
POIWaypoint getWaypoint(long id);
#Query("SELECT pw.*, rw.index_of_route as 'index' FROM POIWaypoint as pw Join RouteWaypoint as rw on (rw.waypointId = pw.id) where rw.routeId = :id order by 'index' ASC")
List<POIRouteStep> getWaypointsFromRoute(int id);

Related

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

#ElementCollection does not getting detached

My goal is to clone entity 'Product' with all its filters.
For example, I have an entity (getters and setters omitted for simplicity):
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ElementCollection()
private List<Filter> filters = new ArrayList<Filter>();
}
And embeddable class:
#Embeddable
public class Filter {
#Column(length = 255, nullable = false)
private String name;
#Column(nullable = false)
private long variant = -1;
}
Now, if I do:
entityManager.detach(product);
product.setId(null);
productService.save(product);
I will get a copy of product entity but with filters from original product. In meanwhile original product will end up with no filters at all..
Thats how filter's table rows looks like:
Before:
product_id; name; variant
217; "f2"; 86
After:
product_id; name; variant
218; "f2"; 86
I tried detach each filter from the list but it gives me error.
How can I make it copy filters with an entity?
Edit: Added full Product and Filter code:
package com.serhiy1.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.SortableField;
import org.joda.time.DateTime;
import com.serhiy1.constraint.LocalePacker;
#Indexed
#Entity
#EntityListeners(ProductListener.class)
public class Product {
public static final int PRICE_PER_ONE = 0;
public static final int PRICE_PER_METER = 1;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long code;
private String name = "";
private String grouping = "";
#Field
#Column(columnDefinition="text")
private String title = "";
#Field
#Column(columnDefinition="text")
private String intro = "";
#Column(columnDefinition="text")
private String content = "";
#Field
#Column(columnDefinition="text")
private String contentHtml = "";
private String locale = "en";
private Long parentId = 0L;
private DateTime time;
private DateTime timeMod;
private Long balanceRequired = 0L;
private Integer index = 0;
#Field(name = "price_sort")
#SortableField(forField = "price_sort")
private Double price = 0.0;
private Integer pricePer;
#Transient
private long childrenCount = 0;
#Transient
private String image = "";
#Transient
private List<String> images = new ArrayList<String>();
#ManyToOne(targetEntity = User.class)
#JoinColumn(nullable = false, name = "user_id")
#LazyCollection(LazyCollectionOption.FALSE)
private User user;
#ManyToOne(targetEntity = Product.class)
#JoinColumn(nullable = true, name = "category_id")
#LazyCollection(LazyCollectionOption.FALSE)
private Product category;
#ElementCollection()
private List<Filter> filters = new ArrayList<Filter>();
#ElementCollection()
private List<Modifier> modifiers = new ArrayList<Modifier>();
public Product() {
}
#Transient
private String _title = "";
#Transient
private String _intro = "";
#Transient
private String _content = "";
#Transient
private String _contentHtml = "";
public void pack(String locale, List<String> locales) {
if(locale.contains("_")) return;
title = LocalePacker.repack(locale, _title, title, locales);
intro = LocalePacker.repack(locale, _intro, intro, locales);
content = LocalePacker.repack(locale, _content, content, locales);
contentHtml = LocalePacker.repack(locale, _contentHtml, contentHtml, locales);
}
public void unpack(String locale) {
_title = LocalePacker.unpackStr(locale, title).getOrDefault(locale, "");
_intro = LocalePacker.unpackStr(locale, intro).getOrDefault(locale, "");
_content = LocalePacker.unpackStr(locale, content).getOrDefault(locale, "");
_contentHtml = LocalePacker.unpackStr(locale, contentHtml).getOrDefault(locale, "");
}
public void copy(String landFrom, String landTo) {
title = LocalePacker.copyLang(title, landFrom, landTo);
intro = LocalePacker.copyLang(intro, landFrom, landTo);
content = LocalePacker.copyLang(content, landFrom, landTo);
contentHtml = LocalePacker.copyLang(contentHtml, landFrom, landTo);
}
public Modifier getModifier(String name) {
for(Modifier m: modifiers) {
if(m.getName().equals(name)) return m;
}
return null;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public long getCode() {
return code == null ? id : code;
}
public void setCode(long code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrouping() {
return grouping;
}
public void setGrouping(String grouping) {
this.grouping = grouping;
}
public String getTitle() {
return _title;
}
public void setTitle(String title) {
this._title = title;
}
public String getIntro() {
return _intro;
}
public void setIntro(String intro) {
this._intro = intro;
}
public String getContent() {
return _content;
}
public void setContent(String content) {
this._content = content;
}
public String getContentHtml() {
return _contentHtml;
}
public void setContentHtml(String contentHtml) {
this._contentHtml = contentHtml;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public long getParentId() {
return parentId;
}
public void setParentId(long parentId) {
this.parentId = parentId;
}
public DateTime getTime() {
return time;
}
public void setTime(DateTime time) {
this.time = time;
}
public DateTime getTimeMod() {
return timeMod;
}
public void setTimeMod(DateTime timeMod) {
this.timeMod = timeMod;
}
public long getBalanceRequired() {
return balanceRequired == null ? 0L : balanceRequired;
}
public void setBalanceRequired(long balanceRequired) {
this.balanceRequired = balanceRequired;
}
public Integer getIndex() {
//return index == null ? 1000 : index;
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public double getPrice() {
return price == null ? 0.0 : price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPricePer() {
return pricePer == null ? PRICE_PER_METER : pricePer;
}
public void setPricePer(int pricePer) {
this.pricePer = pricePer;
}
public long getChildrenCount() {
return childrenCount;
}
public void setChildrenCount(long childrenCount) {
this.childrenCount = childrenCount;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Product getCategory() {
return category;
}
public void setCategory(Product category) {
this.category = category;
}
public List<Filter> getFilters() {
return filters;
}
public void setFilters(List<Filter> filters) {
this.filters = filters;
}
public List<Modifier> getModifiers() {
return modifiers;
}
public void setModifiers(List<Modifier> modifiers) {
this.modifiers = modifiers;
}
public boolean isCategory() { return price < 0; }
#Override
public String toString() {
return "Article{" +
"id=" + id +
'}';
}
}
..
package com.serhiy1.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
#Embeddable
public class Filter {
#Column(length = 255, nullable = false)
private String name;
#Column(nullable = false)
private long variant = -1;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getVariant() {
return variant;
}
public void setVariant(long variant) {
this.variant = variant;
}
}
I made a mini project trying to replicate your issue.
It is a String Boot project with H2 database and JPA (Hibernate implementation).
On startup, Hibernate creates 2 tables:
create table product (
id bigint not null,
primary key (id)
)
and
create table product_filters (
product_id bigint not null,
name varchar(255) not null,
variant bigint not null
)
On product with filters creation, both tables get inserted:
insert
into
product
(id)
values
(1)
and
insert
into
product_filters
(product_id, name, variant)
values
(1, "f1", 1)
After:
entityManager.detach(product);
product.setId(null);
productService.save(product);
Hibernate issues:
delete
from
product_filters
where
product_id=1
which is normal, since filters is an ElementCollection therefore it is totally owned by the entity Product. On productService.save(product) Hibernate detects that filters collection is bound to another Product therefore deletes the old bound (from product_filter table) before creating a new one.
The only way to overcome the deletion is to recreate the collection:
List<Filter> filters = new ArrayList<Filter>();
filters.addAll(oldFilters);
product.setFilters(filters);
To sum up, here is the solution:
// To trigger the fetch
List<Filter> filters = new ArrayList<Filter>(product.getFilters());
entityManager.detach(product);
product.setId(null);
product.setFilters(filters);
productService.save(product);

MySQLIntegrityConstraintViolationException: column "question_id" cannot be null error

i have two entity classes named Qa.java and Answeres.java
my Qa entity consists of lists of answers.
Qa.Java
#Entity
#Table(name = "qa")
public class Qa {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String question;
private String type;
private String description;
private String param;
private int maxlength;
#OneToMany(mappedBy = "qa", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Answers> answersList = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public int getMaxlength() {
return maxlength;
}
public void setMaxlength(int maxlength) {
this.maxlength = maxlength;
}
public List<Answers> getAnswersList() {
return answersList;
}
public void setAnswersList(List<Answers> answersList) {
this.answersList = answersList;
}
}
Answers.java
#Entity
#Table(name = "answers")
public class Answers {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String ans_label;
private int ans_value;
private int ans_weightage;
private int is_default;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "question_id", referencedColumnName = "id",nullable = false)
private Qa qa;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAns_label() {
return ans_label;
}
public void setAns_label(String ans_label) {
this.ans_label = ans_label;
}
public int getAns_value() {
return ans_value;
}
public void setAns_value(int ans_value) {
this.ans_value = ans_value;
}
public int getAns_weightage() {
return ans_weightage;
}
public void setAns_weightage(int ans_weightage) {
this.ans_weightage = ans_weightage;
}
public int getIs_default() {
return is_default;
}
public void setIs_default(int is_default) {
this.is_default = is_default;
}
public Qa getQa() {
return qa;
}
public void setQa(Qa qa) {
this.qa = qa;
}
}
My controller from where i am trying to insert data.
TableDataController.java
#Controller
public class TabletDataController {
#Autowired
QaRepository qaRepository;
#RequestMapping(value = "/saveApiData", method = RequestMethod.GET)
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
}
my qaRepository extends JpaRepository. so whenever i call this api i get an error of com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'question_id' cannot be null
what am i doing wrong?
You have a bidirectional OneToMany relationship, so you need to manually maintain both sides of the relationship. Here you are only setting the Qa side with qa.setAnswersList(answersArrayList);
You need to set the other side of your relationship manually. add:
answers.setQa(qa);
before you save your list
code as follow
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answers.setQa(qa);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
when you save.you should Cascade save.Your annotations configure the relationship of the associated tables but also to associate them when they are saved

org.hibernate.QueryException: could not resolve property: MetadataForHibernate of: bookshare.entity.hasbooks.HasBooks

this is the first time I'm working with Hibernate and I want to make this simple query in Hibernate: sql query
I've tried every thing but every time I get the same error output:
org.hibernate.QueryException: could not resolve property: MetadataForHibernate of: bookshare.entity.hasbooks.HasBooks [SELECT H.MetadataForHibernate FROM
Function I made:
#SuppressWarnings("unchecked")
public List<MetadataForHibernate> getBooksByTitle(int userID, String Title) {
Configuration cfg = new Configuration();
cfg.configure("hibernate.cfg.xml");
SessionFactory factory = cfg.buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(
"SELECT H.MetadataForHibernate FROM HasBooks as H WHERE H.users.id = :userid AND LOWER(H.MetadataForHibernate.title) LIKE LOWER(:title) ORDER BY B.title ASC ");
query.setParameter("userid", userID);
query.setParameter("title", "%" + Title + "%");
List<MetadataForHibernate> books = (List<MetadataForHibernate>) query.list();
tx.rollback();
session.close();
factory.close();
return books;
}
MetadataForHibernate:
#Entity
#Table(name="tblbooks")
public class MetadataForHibernate {
#Id
#Column(name = "bookshareId")
private int bookshareId;
#Column(name="author")
private String author;
#Column(name = "availableToDownload")
private int availableToDownload;
#Column(name = "briefSynopsis")
private String briefSynopsis;
#Column(name="category")
private String category;
#Column(name = "completeSynopsis")
private String completeSynopsis;
#Column(name = "contentId")
private int contentId;
#Column(name = "copyright")
private Date copyright;
#Column(name="downloadFormat")
private String downloadFormat;
#Column(name="dtbookSize")
private int dtbookSize;
#Column(name = "freelyAvailable")
private int freelyAvailable;
#Column(name = "brf")
private int brf;
#Column(name = "daisy")
private int daisy;
#Column(name = "images")
private int images;
#Column(name = "isbn13")
private String isbn13;
#Column(name="language")
private String language;
#Column(name = "publishDate")
private Date publishDate;
#Column(name = "publisher")
private String publisher;
#Column(name = "quality")
private String quality;
#Column(name = "title")
private String title;
#OneToMany(mappedBy="book")
private List<HasBooks> hasBooks;
public MetadataForHibernate(){
hasBooks = new ArrayList<HasBooks>();
}
//Getters & Setters
public List<HasBooks> getHasBooks() {
return hasBooks;
}
public void setHasBooks(List<HasBooks> hasBooks) {
this.hasBooks = hasBooks;
}
public int getFreelyAvailable ()
{
return freelyAvailable;
}
public void setFreelyAvailable (String freelyAvailable)
{
this.freelyAvailable = Integer.parseInt(freelyAvailable);
}
public String getCompleteSynopsis ()
{
return completeSynopsis;
}
public void setCompleteSynopsis (String completeSynopsis)
{
this.completeSynopsis = completeSynopsis;
}
public int getDaisy ()
{
return daisy;
}
public void setDaisy (String daisy)
{
this.daisy = Integer.parseInt(daisy);
}
public Date getCopyright ()
{
return copyright;
}
public void setCopyright (Date copyright)
{
this.copyright = copyright;
}
public int getAvailableToDownload ()
{
return availableToDownload;
}
public void setAvailableToDownload (String availableToDownload)
{
this.availableToDownload = Integer.parseInt(availableToDownload);
}
public int getContentId ()
{
return contentId;
}
public void setContentId (String contentId)
{
this.contentId = Integer.parseInt(contentId);
}
public String getPublisher ()
{
return publisher;
}
public void setPublisher (String publisher)
{
this.publisher = publisher;
}
public int getBookshareId ()
{
return bookshareId;
}
public void setBookshareId (String bookshareId)
{
this.bookshareId = Integer.parseInt(bookshareId);
}
public String getAuthor ()
{
return author;
}
public void setAuthor (String author)
{
this.author = author;
}
public String getTitle ()
{
return title;
}
public void setTitle (String title)
{
this.title = title;
}
public String getCategory ()
{
return category;
}
public void setCategory (String category)
{
this.category = category;
}
public String getQuality ()
{
return quality;
}
public void setQuality (String quality)
{
this.quality = quality;
}
public String getIsbn13 ()
{
return isbn13;
}
public void setIsbn13 (String isbn13)
{
this.isbn13 = isbn13;
}
public int getImages ()
{
return images;
}
public void setImages (String images)
{
this.images = Integer.parseInt(images);
}
public String getLanguage ()
{
return language;
}
public void setLanguage (String language)
{
this.language = language;
}
public String getBriefSynopsis ()
{
return briefSynopsis;
}
public void setBriefSynopsis (String briefSynopsis)
{
this.briefSynopsis = briefSynopsis;
}
public int getDtbookSize ()
{
return dtbookSize;
}
public void setDtbookSize (int dtbookSize)
{
this.dtbookSize = dtbookSize;
}
public int getBrf ()
{
return brf;
}
public void setBrf (String brf)
{
this.brf = Integer.parseInt(brf);
}
public Date getPublishDate ()
{
return publishDate;
}
public void setPublishDate (Date publishDate)
{
this.publishDate = publishDate;
}
public String getDownloadFormat ()
{
return downloadFormat;
}
public void setDownloadFormat (String downloadFormat)
{
this.downloadFormat = downloadFormat;
}
#Override
public String toString()
{
return "ClassPojo [freelyAvailable = "+freelyAvailable+", completeSynopsis = "+completeSynopsis+", daisy = "+daisy+", copyright = "+copyright+", availableToDownload = "+availableToDownload+", contentId = "+contentId+", publisher = "+publisher+", bookshareId = "+bookshareId+", author = "+author+", title = "+title+", category = "+category+", quality = "+quality+", isbn13 = "+isbn13+", images = "+images+", language = "+language+", briefSynopsis = "+briefSynopsis+", dtbookSize = "+dtbookSize+", brf = "+brf+", publishDate = "+publishDate+", downloadFormat = "+downloadFormat+"]";
}
public void convertDataOf(BookDetail book) throws ParseException{
DateFormat format;
Date date;
this.bookshareId=book.getBookshare().getBook().getMetadata().getBookshareId();
this.author=String.join(",", book.getBookshare().getBook().getMetadata().getAuthor());
this.availableToDownload=book.getBookshare().getBook().getMetadata().getAvailableToDownload();
this.briefSynopsis=book.getBookshare().getBook().getMetadata().getBriefSynopsis();
this.category=String.join(",", book.getBookshare().getBook().getMetadata().getCategory());
this.completeSynopsis=book.getBookshare().getBook().getMetadata().getCompleteSynopsis();
this.contentId=book.getBookshare().getBook().getMetadata().getContentId();
//convert String to date
format = new SimpleDateFormat("yyyy");
date = format.parse(book.getBookshare().getBook().getMetadata().getCopyright());
this.copyright=date;
this.downloadFormat=String.join(",", book.getBookshare().getBook().getMetadata().getDownloadFormat());
this.dtbookSize=book.getBookshare().getBook().getMetadata().getDtbookSize();
this.freelyAvailable=book.getBookshare().getBook().getMetadata().getFreelyAvailable();
this.brf=book.getBookshare().getBook().getMetadata().getBrf();
this.daisy=book.getBookshare().getBook().getMetadata().getDaisy();
this.images=book.getBookshare().getBook().getMetadata().getImages();
this.isbn13=book.getBookshare().getBook().getMetadata().getIsbn13();
this.language=String.join(",", book.getBookshare().getBook().getMetadata().getLanguage());
//convert String to date
format = new SimpleDateFormat("MMddyyyy");
date = format.parse(book.getBookshare().getBook().getMetadata().getPublishDate());
this.publishDate=date;
this.publisher=book.getBookshare().getBook().getMetadata().getPublisher();
this.quality=book.getBookshare().getBook().getMetadata().getQuality();
this.title=book.getBookshare().getBook().getMetadata().getTitle();
}
}
HasBooks:
#Entity
#Table(name = "tblhasbooks")
public class HasBooks implements Serializable {
//#Column(name = "Id",unique = true,nullable = false)
#Id
#GeneratedValue()
private int hasBooksId;
#ManyToOne(cascade = CascadeType.ALL)
private Users user;
#ManyToOne(cascade = CascadeType.ALL)
private MetadataForHibernate book;
public MetadataForHibernate getBook() {
return book;
}
public Users getUser() {
return user;
}
public int getHasBooksId() {
return hasBooksId;
}
public void setHasBooksId(int hasBooksId) {
this.hasBooksId = hasBooksId;
}
public void setUser(Users user) {
this.user = user;
}
public void setBook(MetadataForHibernate book) {
this.book = book;
}
}
Users:
#Entity
#Table(name="tblusers")
public class Users implements Serializable{
public Users(){hasBooks = new ArrayList<HasBooks>();
}
#Id
#Column(name = "Id",unique = true,nullable = false)
#GeneratedValue(strategy=GenerationType.AUTO)
private int Id;
#Column(name = "email")
private String email;
#Column(name = "password")
private String password;
#OneToMany(mappedBy="user")
private List<HasBooks> hasBooks;
//Getters & Setters
public List<HasBooks> getHasBooks() {
return hasBooks;
}
public void setHasBooks(List<HasBooks> hasBooks) {
this.hasBooks = hasBooks;
}
public int getId() {
return Id;
}
public void setUser_id(int Id) {
this.Id = Id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
You need to specify a property name, not a property type.
SELECT H.MetadataForHibernate FROM HasBooks as H
need to be corrected to
SELECT H.book FROM HasBooks H
And you need a join to check a book properties
SELECT book
FROM HasBooks H inner join H.book book
where book.title :=title
The query you have written is not valid Hibernate Query Language (HQL), check the documentation for hints, or you can always use a native query to get an Object[] list from the result set, keeping the query you already have.

Caused by: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number in JPA HIBERNATE HQL

Having this class
#Entity
public class PriorityAreaKeyword {
public enum PriorityAreaKey {
ALL ("ALL", "ALL DEVICES"),
IOS ("IOS", "IOS"),
ANDROID ("ANDROID","ANDROID");
private final String name;
private final String id;
private PriorityAreaKey(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
#Id
private Long id;
#Column(name = "key")
#Enumerated(EnumType.STRING)
private PriorityAreaKey key;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public PriorityAreaKey getKey() {
return key;
}
public void setKey(PriorityAreaKey key) {
this.key = key;
}
public List<PriorityArea> getPriorityAreas() {
return priorityAreas;
}
public void setPriorityAreas(List<PriorityArea> priorityAreas) {
this.priorityAreas = priorityAreas;
}
}
I have in the DAO this method that is working fine:
#Override
#SuppressWarnings("unchecked")
public Set<PriorityArea> findPriorityAreas(PriorityAreaKey key) {
String jpql = "from PriorityAreaKeyword as pak where pak.key = :key";
Query query = entityManager.createQuery(jpql);
query.setParameter("key", key);
List<PriorityArea> priorityAreas = query.getResultList();
return new HashSet<PriorityArea>(priorityAreas);
}
I created a view like this v_report_beneficiary_list (id, email, priority_area_key)
/**
*
*/
#Entity
#Table(name = "v_report_beneficiary_list")
public class ReportBeneficiaryItem {
private Long id;
private String email;
private PriorityAreaKey priorityAreaKey;
/**
* #return the id
*/
#Id
public Long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "priority_area_key")
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}
public void setPriorityAreaKey(PriorityAreaKey priorityAreaKey) {
this.priorityAreaKey = priorityAreaKey;
}
In the DAO I've created another method like this:
#Su
ppressWarnings("unchecked")
#Override
public List<ReportBeneficiaryItem> findReportProposalXBeneficiary(ProposalExportFilter filter) {
// Create basic query
String jpql = "from " + ReportBeneficiaryItem.class.getName() + " b where b.priorityAreaKey = :key ";
// Create and execute jpa query
Query query = createQuery(jpql);
query.setParameter("key", filter.getPriorityAreaKey());
return query.getResultList();
}
That throws me a throws me an Exception Caused By: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
You are missing #Enumerated(EnumType.STRING) on ReportBeneficiaryItem#getPriorityAreaKey() as you have on PriorityAreaKeyword#key, so it's expecting numbers (enum index) in the database for that field, but finds strings
#Column(name = "priority_area_key")
#Enumerated(EnumType.STRING)
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}

Categories