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);
Related
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);
When ever I add new child record I have a garbage value that starts appearing in FK column.Following are my classes and database values.
I am not sure whether I am putting any JPA or hibernate annotation wrong or is it a code issue.
Parent Class:
#Component
#Entity
#NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int parentRef;
private BigDecimal price;
private int prod_ID;
private String prodType;
private String remarks;
private int supplier_ID;
private String UOM;
public Product() {
}
#Column(name = "Name")
public String getName() {
return this.name;
}
#Column(name = "ParentRef")
public int getParentRef() {
return this.parentRef;
}
#Column(name = "Price")
public BigDecimal getPrice() {
return this.price;
}
#Id
#Column(name = "Prod_ID")
public int getProd_ID() {
return this.prod_ID;
}
#Column(name = "ProdType")
public String getProdType() {
return this.prodType;
}
#Column(name = "Remarks")
public String getRemarks() {
return this.remarks;
}
#Column(name = "Supplier_ID")
public int getSupplier_ID() {
return this.supplier_ID;
}
#Column(name = "UOM")
public String getUOM() {
return this.UOM;
}
public void setName(String name) {
this.name = name;
}
public void setParentRef(int parentRef) {
this.parentRef = parentRef;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setProd_ID(int prod_ID) {
this.prod_ID = prod_ID;
}
public void setProdType(String prodType) {
this.prodType = prodType;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public void setSupplier_ID(int supplier_ID) {
this.supplier_ID = supplier_ID;
}
public void setUOM(String UOM) {
this.UOM = UOM;
}
#Override
public String toString() {
return "Name = "+ this.getName() +"\n ParentRef="+this.getParentRef() +"\n Prod ID="+this.getProd_ID() +"\n ProdType= "+getProdType() +"\n Remarks= "+getRemarks()+"\n Supplier_ID="+getSupplier_ID()+"\n UOM = "+getUOM()+"\nPrice ="+getPrice();
}
}
Child Class:
#Entity(name="Productdetail")
public class ProductDetail implements Serializable {
private static final long serialVersionUID = 1L;
#Column(nullable=true , name = "Color")
private String Color;
#Column(nullable=true , name = "Designno")
private String DesignNo;
#Column(nullable=true , name = "Imgpath")
private String ImgPath;
#Column(nullable=true , name = "IsScrap")
private Integer IsScrap;
private Product Prod_ID;
#Id
#TableGenerator(
name="ProdDetailID",
table="ID_GEN",
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="ProdDetailID",
allocationSize=1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="ProdDetailID")
#Column(name = "Proddetail_ID")
private Integer ProdDetail_ID;
#Column(nullable=true , name = "Remarks")
private String Remarks;
public ProductDetail() {
}
public ProductDetail(String remarks, String imgPath, String designNo, String color, Integer isScrap,
Integer prodDetail_ID) {
super();
Remarks = remarks;
ImgPath = imgPath;
DesignNo = designNo;
Color = color;
IsScrap = isScrap;
//Prod_ID = prod_ID;
ProdDetail_ID = prodDetail_ID;
}
public String getColor() {
return Color;
}
public String getDesignNo() {
return DesignNo;
}
public String getImgPath() {
return ImgPath;
}
public Integer getIsScrap() {
return IsScrap;
}
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="Prod_ID" )
public Product getProd_ID() {
return Prod_ID;
}
public Integer getProdDetail_ID() {
return ProdDetail_ID;
}
public String getRemarks() {
return Remarks;
}
public void setColor(String color) {
Color = color;
}
public void setDesignNo(String designNo) {
DesignNo = designNo;
}
public void setImgPath(String imgPath) {
ImgPath = imgPath;
}
public void setIsScrap(Integer isScrap) {
IsScrap = isScrap;
}
public void setProd_ID(Product prod_ID) {
Prod_ID = prod_ID;
}
public void setProdDetail_ID(Integer prodDetail_ID) {
ProdDetail_ID = prodDetail_ID;
}
public void setRemarks(String remarks) {
Remarks = remarks;
}
}
CONTROLLER:
#PostMapping(value="/save")
private void SaveData(#ModelAttribute ProductDetail productDetail ,#RequestParam("Product") int productID) {
productDetail.setProd_ID( getProductList().get(productID) );
System.out.println(productDetail.getProd_ID());
prodDetailService.save(productDetail);
}
#GetMapping(value = "/NewOrder")
public String NewProduct(Model model) {
model.addAttribute("product", new Product());
model.addAttribute("productDetail", new ProductDetail());
model.addAttribute("order", new Order());
model.addAttribute("orderDetial", new OrderDetail());
model.addAttribute("productList", getProductList());
return "NewOrder"; // Returns page named mentioned
}
protected List<Product> getProductList() {
productlist = new ArrayList<Product>();
productlist = ProdService.findAll();;
return productlist;
}
Database value of child table are :
Prod_ID is containing some unknown values.
ProdDetail_ID Prod_ID Color DesignNo ImgPath IsScrap Remarks
------------- ---------- ----- --------- ------- ------- -------
3 **1946157361** Red design NULL NULL NULL
4 **1946157361** Red design NULL NULL NULL
Parent table is :
Prod_ID Name Price UOM ProdType ParentRef Supplier_ID Remarks
------- ---------- ----- ----- -------- --------- ----------- -------
1 Lawn NULL pcs 2 pcs 1 1 1
2 TestData 2500 Meter 3 0 1 Remarks
Please help me out to solve this issue.
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.
I read a CSV file with university courses (11000 rows) and want to insert this using hibernate into a MySQL database. The problem is that hibernate inserts each row twice. There is a bug regarding this issue. Solution should be to flush each child after persisting.
See here: Hibernate inserts duplicates into a #OneToMany collection and https://hibernate.atlassian.net/browse/HHH-6776
Here is the code from my Spring applications controller:
#RequestMapping(value = "/readcsv")
public String readCSVFile() {
entityManager.setFlushMode(FlushModeType.COMMIT);
//Load all courses and universities and add to hashmap for fast lookup.
ArrayList<Course> allCourses = (ArrayList) entityManager.createQuery("FROM Course").getResultList();
MultiValueMap courseMap = MultiValueMap.decorate(new HashMap<String, Course>());
for (Course c : allCourses) {
courseMap.put(c.getName(), c);
}
ArrayList<University> allUniversities = (ArrayList) entityManager.createQuery("FROM University").getResultList();
HashMap<String, University> universityMap = new HashMap<String, University>();
for (University u : allUniversities) {
universityMap.put(u.getName(), u);
}
Country sweden = (Country) entityManager.createQuery("SELECT c FROM Country c WHERE c.name = 'Sweden'").getSingleResult();
ArrayList<Course> coursesToAdd = new ArrayList<Course>();
//Set fixed parameters for this specific dataset.
String filename = "/Volumes/320gb/macbookpro/Documents/AntagningsstatistikVT2015.csv";
String semester = "Spring2015";
String type = "Classroom";
int pace = 100;
University u;
try {
//Read file
File fileDir = new File(filename);
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fileDir), "UTF-8"));
String line;
//Loop lines in file
while ((line = in.readLine()) != null) {
// use comma as separator
String[] courseLine = line.split(",");
String name = courseLine[1];
String university = courseLine[2];
//See if the course is already in the database
Collection<Course> coursesWithSameName = courseMap.getCollection(name);
boolean found = false;
if (coursesWithSameName != null) {
for (Course course: coursesWithSameName) {
if (course.getUniversity().getName().equals(university)) {
System.out.println("COURSE ALREADY IN DB : " + name + " " + university);
found = true;
}
}
}
//If not, insert it
if (found == false) {
if (!universityMap.containsKey(university)) {
u = new University();
u.setName(university);
u.setCountry(sweden);
u.setUserAdded(false);
universityMap.put(u.getName(), u);
entityManager.persist(u);
entityManager.flush();
} else {
u = universityMap.get(university);
}
Course course = new Course();
course.setName(name);
course.setUniversity(u);
course.setType(type);
course.setPace(pace);
course.setSemester(semester);
courseMap.put(course.getName(), course);
coursesToAdd.add(course);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("NUMBER OF ROWS IN coursesToAdd : " + coursesToAdd.size()); //Correctly prints 11000
for (Course course : coursesToAdd) { //inserts 22000 rows to db.
entityManager.persist(course);
entityManager.flush();
}
return "redirect:/";
}
Even though I flush after each persist double rows gets inserted. I have the #Transactional annotation on the controller class, is this the reason flush doesn't solve the problem? It however seems much slower when having flush there, which seems like it runs correctly compared to when it does a bulk insert on the end without flushing each insert.
Someone have a clue what is wrong in my code?
Thank you!
Edit:
Added University and Course entities:
Course:
import com.courseportal.project.account.Account;
import com.courseportal.project.utils.AbstractTimestampEntity;
import org.hibernate.annotations.Cascade;
import java.io.Serializable;
import java.util.List;
import javax.persistence.*;
#Entity
#Table(name="courses")
public class Course extends AbstractTimestampEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
#Column(name = "code")
private String code;
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("date desc")
private List<CourseRank> ranks;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("date desc")
private List<Comment> comments;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("date desc")
private List<UserBook> userBooks;
#ElementCollection
private List<CourseBook> courseBooks;
#ManyToMany
#JoinTable(name="courses_enrolledStudents")
private List<Account> enrolledStudents;
#OneToMany(cascade = CascadeType.ALL)
private List<Timeslot> times;
#ManyToOne
private University university;
/*
* fall
* spring
* summer
*/
private String semester;
private String teacherName;
private String courseLink;
private String requirementsLink;
/**
* Undergraduate
* Graduate
*/
private String level;
/**
* Online (MOOC - Massive Open Online Courses)
* Classroom (Traditional)
* Mixed (Lab)
*/
private String type;
/**
* How fast the course going in percentage.
*/
private int pace;
private int numberOfAssignments;
private int numberOfProjects;
private int numberOfExams;
private double credits;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public University getUniversity() {
return university;
}
public void setUniversity(University university) {
this.university = university;
}
public String getCourseLink() {
return courseLink;
}
public void setCourseLink(String courseLink) {
this.courseLink = courseLink;
}
public String getRequirementsLink() {
return requirementsLink;
}
public void setRequirementsLink(String requirementsLink) {
this.requirementsLink = requirementsLink;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public List<Timeslot> getTimes() {
return times;
}
public void setTimes(List<Timeslot> times) {
this.times = times;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPace() {
return pace;
}
public void setPace(int pace) {
this.pace = pace;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
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 List<CourseRank> getRanks() {
return ranks;
}
public void setRanks(List<CourseRank> ranks) {
this.ranks = ranks;
}
public void addRank(CourseRank rank) {
this.ranks.add(rank);
}
public void removeRank(CourseRank rank) {
this.ranks.remove(rank);
}
public void addComment(Comment comment) {
comments.add(comment);
}
//User books, books that are for sale getters and setters
public void removeUserBook(UserBook book) {
this.userBooks.remove(book);
}
public void addUserBook(UserBook book) {
this.userBooks.add(book);
}
public List<UserBook> getUserBooks() {
return userBooks;
}
public void setUserBooks(List<UserBook> userBooks) {
this.userBooks = userBooks;
}
public List<CourseBook> getCourseBooks() {
return courseBooks;
}
public void setCourseBooks(List<CourseBook> courseBooks) {
this.courseBooks = courseBooks;
}
public void removeCourseBook(CourseBook book) {
this.courseBooks.remove(book);
}
public void addCourseBook(CourseBook book) {
this.courseBooks.add(book);
}
public int getNumberOfAssignments() {
return numberOfAssignments;
}
public void setNumberOfAssignments(int numberOfassignments) {
this.numberOfAssignments = numberOfassignments;
}
public int getNumberOfProjects() {
return numberOfProjects;
}
public void setNumberOfProjects(int numberOfprojects) {
this.numberOfProjects = numberOfprojects;
}
public int getNumberOfExams() {
return numberOfExams;
}
public void setNumberOfExams(int numberOfexams) {
this.numberOfExams = numberOfexams;
}
public double getCredits() {
return credits;
}
public void setCredits(double credits) {
this.credits = credits;
}
public List<Account> getEnrolledStudents() {
return enrolledStudents;
}
public void setEnrolledStudents(List<Account> enrolledStudents) {
this.enrolledStudents = enrolledStudents;
}
public void addEnrolledStudent(Account student) {
this.enrolledStudents.add(student);
}
public void removeEnrolledStudent(Account student) {
this.enrolledStudents.remove(student);
}
public String getSemester() {
return semester;
}
public void setSemester(String semester) {
this.semester = semester;
}
}
And University:
import com.courseportal.project.utils.AbstractTimestampEntity;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="universities")
public class University extends AbstractTimestampEntity implements Serializable {
#Id
#GeneratedValue
private int id;
private String name;
#ManyToOne
private Country country;
private boolean userAdded;
public University() {}
public University(String university) {
name = university;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isUserAdded() {
return userAdded;
}
public void setUserAdded(boolean userAdded) {
this.userAdded = userAdded;
}
}
I am having problem in removing data from my arraylist by its id.
I have a books in my arraylist and i want to remove a particular books based on its id.
I tried the below code but my data is not removing.
Please check my code below and suggest a solution for it.
Update
When i calls this method then compiler reads all the below code but it does not removes my data from my arraylist. I am not getting any error.
-------------------
-------------------
public String removebookfrmSession()
{
List<Bookdetails> books = new ArrayList<Bookdetails>();
String bookid = request.getParameter("bkid");
Bookdetails book = dao.listBookDetailsById(Integer.parseInt(bookid));
books = (ArrayList) session.get(BillTransactionBooksConstants.BOK);
if ( books == null ) books = new ArrayList<Bookdetails>();
boolean already_exists = false;
for ( Bookdetails b : books )
{
if ( Integer.toString(b.getId()).equals(bookid))
{
already_exists = true;
break;
}
}
if (book != null && already_exists )
{
books.remove(book);
System.out.println("books size"+books.size());
session.put(BillTransactionBooksConstants.BOK,books);
}
return SUCCESS;
}
Bookdetails.java (POJO)
package v.esoft.pojos;
// Generated Nov 5, 2012 9:37:14 PM by Hibernate Tools 3.4.0.CR1
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Bookdetails generated by hbm2java
*/
#Entity
#Table(name = "bookdetails", catalog = "vbsoftware")
public class Bookdetails implements java.io.Serializable {
private Integer id;
private String isbn;
private String bookTitile;
private String authFirstname;
private String authLastname;
private String editionYear;
private Integer subjectId;
private Integer coverId;
private Integer languageId;
private String publisherName;
private Integer editionId;
private Float price;
private String quantity;
private String description;
private Integer locationId;
private String remarks;
private String img1;
private String img2;
private String videoUrl;
private Integer createrId;
private Date createdDate;
private Integer updateId;
private Date updatedDate;
public Bookdetails() {
}
public Bookdetails(String isbn, String bookTitile, String authFirstname,
String authLastname, String editionYear, Integer subjectId,
Integer coverId, Integer languageId, String publisherName,
Integer editionId, Float price, String quantity,
String description, Integer locationId, String remarks,
String img1, String img2, String videoUrl, Integer createrId,
Date createdDate, Integer updateId, Date updatedDate) {
this.isbn = isbn;
this.bookTitile = bookTitile;
this.authFirstname = authFirstname;
this.authLastname = authLastname;
this.editionYear = editionYear;
this.subjectId = subjectId;
this.coverId = coverId;
this.languageId = languageId;
this.publisherName = publisherName;
this.editionId = editionId;
this.price = price;
this.quantity = quantity;
this.description = description;
this.locationId = locationId;
this.remarks = remarks;
this.img1 = img1;
this.img2 = img2;
this.videoUrl = videoUrl;
this.createrId = createrId;
this.createdDate = createdDate;
this.updateId = updateId;
this.updatedDate = updatedDate;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "isbn", length = 90)
public String getIsbn() {
return this.isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
#Column(name = "book_titile")
public String getBookTitile() {
return this.bookTitile;
}
public void setBookTitile(String bookTitile) {
this.bookTitile = bookTitile;
}
#Column(name = "auth_firstname", length = 120)
public String getAuthFirstname() {
return this.authFirstname;
}
public void setAuthFirstname(String authFirstname) {
this.authFirstname = authFirstname;
}
#Column(name = "auth_lastname", length = 120)
public String getAuthLastname() {
return this.authLastname;
}
public void setAuthLastname(String authLastname) {
this.authLastname = authLastname;
}
#Column(name = "edition_year", length = 20)
public String getEditionYear() {
return this.editionYear;
}
public void setEditionYear(String editionYear) {
this.editionYear = editionYear;
}
#Column(name = "subject_id")
public Integer getSubjectId() {
return this.subjectId;
}
public void setSubjectId(Integer subjectId) {
this.subjectId = subjectId;
}
#Column(name = "cover_id")
public Integer getCoverId() {
return this.coverId;
}
public void setCoverId(Integer coverId) {
this.coverId = coverId;
}
#Column(name = "language_id")
public Integer getLanguageId() {
return this.languageId;
}
public void setLanguageId(Integer languageId) {
this.languageId = languageId;
}
#Column(name = "publisher_name", length = 70)
public String getPublisherName() {
return this.publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
#Column(name = "edition_id")
public Integer getEditionId() {
return this.editionId;
}
public void setEditionId(Integer editionId) {
this.editionId = editionId;
}
#Column(name = "price", precision = 12, scale = 0)
public Float getPrice() {
return this.price;
}
public void setPrice(Float price) {
this.price = price;
}
#Column(name = "quantity", length = 40)
public String getQuantity() {
return this.quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
#Column(name = "description", length = 65535)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "location_id")
public Integer getLocationId() {
return this.locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
#Column(name = "remarks", length = 65535)
public String getRemarks() {
return this.remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
#Column(name = "img1")
public String getImg1() {
return this.img1;
}
public void setImg1(String img1) {
this.img1 = img1;
}
#Column(name = "img2")
public String getImg2() {
return this.img2;
}
public void setImg2(String img2) {
this.img2 = img2;
}
#Column(name = "video_url", length = 65535)
public String getVideoUrl() {
return this.videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
#Column(name = "creater_id")
public Integer getCreaterId() {
return this.createrId;
}
public void setCreaterId(Integer createrId) {
this.createrId = createrId;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_date", length = 19)
public Date getCreatedDate() {
return this.createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
#Column(name = "update_id")
public Integer getUpdateId() {
return this.updateId;
}
public void setUpdateId(Integer updateId) {
this.updateId = updateId;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_date", length = 19)
public Date getUpdatedDate() {
return this.updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
}
Your Bookdetails class must implement the public boolean equals(Object o) method in order to use the List#remove(Object o) method. Otherwise, you should handle the object removal by yourself as stated by #juergend.
Implementing the equals method would be like this:
public class Bookdetails {
private int id;
//other attributes and methods...
#Override
public boolean equals(Object o) {
if (o instanceof Bookdetails) {
Bookdetails oBookdetails = (Bookdetails)o;
return (this.id == oBookdetails.id);
}
return false;
}
}
Now the books.remove(book); would work without need of the for ( Bookdetails b : books ) loop.
Default equality is based on reference so you need to assign book to reference from the list so that remove will work. Or you can override equals but I am not quite sure whether you can provide equality on bookId
for ( Bookdetails b : books )
{
if ( Integer.toString(b.getId()).equals(bookid))
{
already_exists = true;
book= b;
break;
}
}
Then when you call remove because of reference equality it will remove book
Update:
If its POJO and you have primary key then you can easily implement equals on primary key that is id. No need to iterate over the list.