I am creating a website that will have articles; each article will have comments. These comments will be stored in a "comment" table with a field called "parent_id" that is a foreign key to the field "id" in the same table.
I am hoping to use Hibernate to recursively grab all of the comments for a specific article.
Here is my Entity:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
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.OneToMany;
import org.hibernate.annotations.IndexColumn;
#Entity
public class Comment implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#ManyToOne
#JoinColumn(name="user_id")
private User user;
#OneToMany(targetEntity=Comment.class)
#JoinColumn(name="parent_id")
#IndexColumn(name="id", base=0)
private List<Comment> comments = new ArrayList<Comment>();
#Column(name="article_id", length=10)
private int articleId;
#Column(name="text", length=8192)
private String text;
public int getArticleId() {
return articleId;
}
public void setArticleId(int articleId) {
this.articleId = articleId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public String toString() {
return "Comment [" + "articleId " + articleId + " " + "id " + id + " " + "text " + text + " " + "]";
}
}
The code is "kinda" working, however, when all of the comments are retrieved the "child" list of comments contains the same number of elements as there are total comments (if that makes sense. For instance, assume I have only three comments in the table for article with id number 1... this article with 2 comments, and one of the comments has a child comment.. the array with the child comment has 3 entries, the first 2 are null and the last is the child comment.
Is this code correct?
I wonder if the problem is not coming from the fact that you are using the PK column as index column. I'd recommend to use a dedicated column for the index column. Something like this:
#OneToMany
#JoinColumn(name="parent_id")
#IndexColumn(name="comments_index", base=0)
private List<Comment> comments = new ArrayList<Comment>();
Could you give this a try?
Related
So I have repository defined as follows:
public interface PersonRepository extends CrudRepository<Person, Long>
My entity is as follows:
#Entity
#Table(name="Person")
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="PERSON_GENERATOR", sequenceName="PERSON_SEQ")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERSON_GENERATOR")
private Long id;
#Column(name="ssn")
private String socialSecurityNumber;
private String name;
public Person() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
I have ommitted the getters and setters for socialSecurityNumber and Name. In the database there are 1000 records.
I have a Spring bean annotated with #Component that uses the PersonRepo by calling its findAll(). When findAll() gets called I get the list of 1000 records with their UNIQUE ID however, when I loop through the list of Persons returned by findAll() I find unexpected results.
#Component
public class PersonComponent {
#Autowired
PersonRepository personRepo;
public void printPerson() {
List<Person> people = personRepo.findAll();
for(Person person : people) {
System.out.println("id=" + person.getId() + ", ssn=" + person.getSocialSecurityNumber() + ", name=" + person.getName());
}
}
}
So if in my db i have the records
id, ssn, name
1, ssn1, Bob
2, ssn2, Mary
3, ssn3, Joe
when I call the findAll() I constantly get this back
id=1, ssn=ssn1, name=Bob
id=2, ssn=ssn2, name=Mary
id=3, ssn=ssn2, name=Mary
Notice that i get the correct Ids (ie. 1, 2, 3) but for some reason id 3 is mapped to ssn2,Mary and NOT ssn3, Joe
This behaviour happens only after the first call to findAll() (ie. the first findAll, works fine but subsequent once show the behaviour explained above). In other words, when the application starts up and the Spring bean that uses the PersonRepo gets called for the first time, findAll() seems to work fine. But when a subsequent call is made to the Spring Bean then findAll behaves as described.
Lastly, When i call the web service http://localhost/persons (which calls `findAll() under the covers) I get the correct behaviour every time.
Any thoughts?
The problem is probably relating to omitting getters and setters for name and social security variables ? After all those are declared private so we need a way to access them, hence why getters ?
I have replicated your app and if you use the following, you should not be getting duplicates at all.
Appllication.properties file:
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/findall_db
spring.datasource.username=YOUR_DATABASE_USERNAME
spring.datasource.password=YOUR_DATABASE_PASSWORD
Person Entity Java Class:
package com.example.demo;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name="Person")
public class PersonInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="PERSON_GENERATOR", sequenceName="PERSON_SEQ")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERSON_GENERATOR")
private Long id;
#Column(name="ssn")
private String socialSecurityNumber;
private String name;
public PersonInfo() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
public void setSocialSecurityNumber(String socialSecurityNumber) {
this.socialSecurityNumber = socialSecurityNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "PersonInfo [id=" + id + ", socialSecurityNumber=" + socialSecurityNumber + ", name=" + name + "]";
}
}
Person Repository:
package com.example.demo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface PersonInfoRepository extends CrudRepository<PersonInfo, Long>{
}
Person Controller:
package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#Controller
public class PersonController {
#Autowired
PersonInfoRepository personRepo;
#ResponseBody
#GetMapping("/people")
public List printPersonInfo() {
List<PersonInfo> people = (List<PersonInfo>) personRepo.findAll();
System.out.println(people.toString());
return people ;
}
}
I was trying to make a crud app which has two model objects of type Muscle and Exercise. Basically One Muscle Object can have a list of Exercise objects. I wanted to implement the CRUD operations for the both the model object. For Muscle object it was very straight forward but for the Exercise Object for the put/Update operation I am getting the following error "JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference" . And further more if I try to delete one exercise, somehow all the data of muscle and exercise gets deleted.
This is my muscle class
package com.fazla.exercise.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class Muscle {
#Id
// #Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String name;
#OneToMany(mappedBy="muscle", cascade= CascadeType.ALL, fetch = FetchType.EAGER)
// #JoinColumn(name="muscle_id")
// #Column(nullable = true)
private List<Exercise> exercises = new ArrayList<>();
public Muscle() {
}
public Muscle(String name, List<Exercise> exercises) {
super();
this.name = name;
this.exercises = exercises;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Exercise> getExercises() {
return exercises;
}
public void setExercises(List<Exercise> exercises) {
this.exercises = exercises;
}
// #Override
// public String toString() {
// return "Muscle [id=" + id + ", name=" + name + ", exercises=" + exercises + "]";
// }
}
This is my Exercise Object
package com.fazla.exercise.model;
import javax.persistence.CascadeType;
import javax.persistence.Column;
//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.JoinTable;
import javax.persistence.ManyToOne;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Entity
//#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class Exercise {
#Id
#Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column
private String name;
#Column
private String description;
//As there will be many exercise under one muscle that is why manytoone
//object references an unsaved transient instance - save the transient instance before flushing
//that is why need to add the cascading dependencies
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="muscle_id")
// #JsonIgnore
// #JoinTable(name="muscle")
private Muscle muscle;
public Exercise() {
}
public Exercise(String name, String description, Muscle muscle) {
super();
this.name = name;
this.description = description;
this.muscle = muscle;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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 Muscle getMuscle() {
return muscle;
}
public void setMuscle(Muscle muscle) {
this.muscle = muscle;
}
// #Override
// public String toString() {
// return "Exercise [id=" + id + ", name=" + name + ", description=" + description + ", muscle=" + muscle + "]";
// }
}
This is the MuscleController
package com.fazla.exercise.controller;
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.fazla.exercise.model.Muscle;
import com.fazla.exercise.repository.MuscleRepository;
#RestController
public class MuscleController {
private MuscleRepository muscleRepository;
public MuscleController(MuscleRepository muscleRepository) {
this.muscleRepository = muscleRepository;
}
#GetMapping("/muscle")
List<Muscle> all(){
return muscleRepository.findAll();
}
#PostMapping("/muscle")
Muscle newMuscle(#RequestBody Muscle muscle) {
return muscleRepository.save(muscle);
}
#GetMapping("/muscle/{id}")
Muscle one(#PathVariable Long id) {
return muscleRepository.findById(id)
.orElse(null);
}
#PutMapping("/muscle/{id}")
Muscle updateMuscle(#RequestBody Muscle newMuscle, #PathVariable Long id) {
return muscleRepository.findById(id)
.map(muscle ->{
muscle.setName(newMuscle.getName());
muscle.setExercises(newMuscle.getExercises());
return muscleRepository.save(muscle);
})
.orElse(null);
}
#DeleteMapping("/muscle/{id}")
void deleteMuscle(#PathVariable Long id){
muscleRepository.deleteById(id);
}
}
This is the ExerciseController Class
package com.fazla.exercise.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fazla.exercise.model.Exercise;
import com.fazla.exercise.model.Muscle;
import com.fazla.exercise.repository.ExerciseRepository;
import com.fazla.exercise.repository.MuscleRepository;
#RestController
public class ExerciseController {
private ExerciseRepository repository;
private MuscleRepository muscleRepository;
#Autowired
public ExerciseController(ExerciseRepository repository, MuscleRepository muscleRepository) {
super();
this.repository = repository;
this.muscleRepository=muscleRepository;
}
#GetMapping("/exercise")
public List<Exercise> getAll() {
return repository.findAll();
}
#PostMapping("/exercise")
public Exercise newExercise(#RequestBody Exercise newExercise, #RequestParam
Long muscleId) {
Muscle muscle = muscleRepository.findById(muscleId).orElse(null);
newExercise.setMuscle(muscle);
return repository.save(newExercise);
}
#DeleteMapping("/exercise/{id}")
public void deleteExercise(#PathVariable Long id) {
repository.deleteById(id);
}
#GetMapping("/exercise/{id}")
public Exercise one(#PathVariable Long id) {
return repository.findById(id).orElse(null);
}
#PutMapping("/exercise/{id}")
public Exercise updateExercise(#RequestBody Exercise newExercise, #PathVariable Long id) {
return repository.findById(id)
.map(//map a function which maps
e ->{
e.setName(newExercise.getName());
e.setDescription(newExercise.getDescription());
e.setMuscle(newExercise.getMuscle());
return repository.save(e);
})
.orElse(null);
}
}
This is my ExerciseRepository
package com.fazla.exercise.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.fazla.exercise.model.Exercise;
public interface ExerciseRepository extends JpaRepository<Exercise, Long> {
}
This is the MuscleRepository
package com.fazla.exercise.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.fazla.exercise.model.Muscle;
public interface MuscleRepository extends JpaRepository<Muscle, Long>{
}
This is the error if I try the put request or update the exercise object
"timestamp": "2018-10-10T06:30:46.924+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for: \n at [Source: (PushbackInputStream); line: 23, column: 1]Object id [1] (for `com.fazla.exercise.model.Muscle`) at [Source: (PushbackInputStream); line: 13, column: 28], Object id [1] (for `com.fazla.exercise.model.Muscle`) at [Source: (PushbackInputStream); line: 19, column: 28].",
"path": "/api/exercise/14"
The solution was, adding orphanRemoval= true on the Parent/ Muscle model
#OneToMany(mappedBy="muscle", cascade= CascadeType.ALL, orphanRemoval= true)
private List<Exercise> exercises = new ArrayList<>();
Removing the cascade= CascadeType.ALL in the child/ Exercise model
#ManyToOne
private Muscle muscle;
And for the updateExercise changing the Request by finding the muscle which the exercise belongs to and muscleRepository.findById(muscleId) and setting it in the new exercise object.
#PutMapping("/exercise/{id}")
public Exercise updateExercise(#RequestBody Exercise newExercise, #PathVariable Long id, #RequestParam Long muscleId) {
Muscle muscle = muscleRepository.findById(muscleId).orElse(null);
return repository.findById(id)
.map(//map a function which maps
e ->{
e.setName(newExercise.getName());
e.setDescription(newExercise.getDescription());
e.setMuscle(muscle);
return repository.save(e);
})
.orElse(null);
}
on your Exercise you have
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="muscle_id")
private Muscle muscle;
and on your Musce you have
#OneToMany(cascade= CascadeType.ALL)
private List<Exercise> exercises = new ArrayList<>();
Cascade.ALL propagates all actions on your Object and if you delete a Excercise, DELETE is propagated to all referenced objects
Bacause you just want to propagate UPDATES replace
cascade = CascadeType.ALL
with
cascade = CascadeType.SAVE_UPDATE
I want to establish one to many relation between table vendor detail and product detail. like one vendor can have multiple products. but when i am inserting data into table its inserting all the four fields but not mapping vendorid into ProductDetail Table
and query generated is this.
Hibernate: insert into ProductInfo (productCategory, productDetails, productPrice, VendorId) values (?, ?, ?, ?) It shuld map vendor ID also but in table its empty.
VendorDetail.java
package com.cts.entity;
import javax.persistence.*;
#Entity
#Table(name = "VendorInfo")
public class VendorDetails {
#Id
#Column
private Long VendorId;
#OneToMany
private ProductDetails productdetail;
#Column
private String VendorName;
#Column
private String Password;
public String getVendorName() {
return VendorName;
}
public void setVendorName(String vendorName) {
VendorName = vendorName;
}
public Long getVendorId() {
return VendorId;
}
public void setVendorId(Long vendorId) {
VendorId = vendorId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
}
ProductDetails.java
package com.cts.entity;
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.OneToOne;
import javax.persistence.Table;
#Entity#Table(name = "ProductInfo")
public class ProductDetails {
#ManyToOne(cascade = CascadeType.ALL)#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
public ProductDetails() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int productId;
#Column
private String productCategory;
#Column
private String productDetails;
#Column
private String productPrice;
public VendorDetails getVendordetails() {
return vendordetails;
}
public void setVendordetails(VendorDetails vendordetails) {
this.vendordetails = vendordetails;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getProductDetails() {
return productDetails;
}
public void setProductDetails(String productDetails) {
this.productDetails = productDetails;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
}
DAO class ProductDetailDaoImpl.java
package com.cts.Dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.cts.entity.ProductDetails;
import com.cts.entity.to.ProductDetailsTo;
#Repository
public class ProductDetailDaoImpl implements ProductDetailDao {
#Autowired
SessionFactory sessionFactory;
#Transactional
public boolean saveProductInfo(ProductDetailsTo productTo) {
System.out.println("M in Registration DAO");
System.out.println(productTo.getProductCategory());
System.out.println(productTo.getProductDetails());
System.out.println(productTo.getProductId());
System.out.println(productTo.getProductPrice());
//getting productTo data to entity class
ProductDetails prodet = productTo.getEntity();
System.out.println("Value of product details is:" + prodet.getProductDetails());
sessionFactory.getCurrentSession().save(prodet);
return false;
}
}
VendorDetails has many ProductDetails so you need to make one to many annotation like this:-
#OneToMany(mappedBy="vendordetails") //mappedBy value will be what you declared //in ProductDetails class.
private Collection<ProductDetails> productdetail=new ArrayList<ProductDetails>;
and create the setter and getter of this.
Now in ProductDetails class you need to annotate many to one like this:-
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
Then a new column named 'VendorId' will be create in table 'ProductInfo' and since declare mappedBy value="vendordetails" so each vendor id would be insert.
I think you should replace the code
#OneToMany
private ProductDetails productdetail;
to
#OneToMany
private Set productdetailSet;
And create setter and getter for this.
You can visit the blog http://gaurav1216.blogspot.in/2014/01/hibernate-tutorial-day-5.html for one to many using annotation.
Here's my User:
package models.user;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import play.data.validation.Constraints.MaxLength;
import play.data.validation.Constraints.MinLength;
import play.data.validation.Constraints.Required;
import play.db.ebean.Model;
#Entity
#Table(name = "T_USER")
public class User extends Model {
#Id
public Long id;
#Required
#MaxLength(30)
#MinLength(4)
public String username;
#Required
#MaxLength(30)
#MinLength(4)
public String password;
#ManyToOne(fetch = FetchType.EAGER)
#Column(nullable = false)
public Role role;
public static Finder<Long, User> find = new Finder<Long, User>(Long.class, User.class);
public User() {
}
public User(String username, String password, Role role) {
this.username = username;
this.password = password;
this.role = role;
}
#Override
public String toString() {
return "[Tying to login : ] [" + username + " - " + password + "]";
}
}
In my controller, I want to get a user's role instance, so here's what I did:
public static Result modules(Long id) {
User user = User.find.byId(id);
if ("Super User".equalsIgnoreCase(user.role.name)) {
return ok();
} else {
return forbidden();
}
}
The problem is, user.role.name is null, but user.role.id is correct here, why EBean doesn't help me to fetch role for users ?
I have experienced this problem on different occasions. You could do the following:
First, try to replace your public fields with private ones and the add the appropriate getters and setters (this is a good pattern when using Java anyway).
Second, you can write a little helper for finding/fetching the needed information. So let's say you need to get the user by Id and the do this string check. Then in your User class you can write a method like this:
public static User findById(Long id) {
return Ebean.find(User.class)
.fetch("role")
.where()
.eq("id", id)
.findUnique();
}
After that, just use the method:
public static Result modules(Long id) {
User user = User.findById(id);
if ("Super User".equalsIgnoreCase(user.getRole().getName())) {
return ok();
} else {
return forbidden();
}
}
please excuse my bad English...
In my database there are stored article sets. In every article sets there are several different articles in it. Each article has a different demand with a date and a quantity.
In the project there is an enum which looks like this:
public enum PeriodDefinition {
Individual,
Day,
Week,
Month,
Quarter,
HalfYear,
Year
}
The entity of Article is like that:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
#Entity
public class Article extends ArticleContainer {
private float price;
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
The entity of Article Container:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
#Entity
public class ArticleContainer extends BaseEntity {
#Column(nullable = false, unique = true)
private String number;
#Column(nullable = false)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
The Entity of Article Set:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
#Entity
public class ArticleSet extends ArticleContainer {
private static final long serialVersionUID = 6236522228097421880L;
#ManyToMany
private List<Article> articles = new ArrayList<Article>();
#OneToMany
private List<ArticleSet> children = new ArrayList<ArticleSet>();
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
public List<ArticleSet> getChildren() {
return children;
}
public void setChildren(List<ArticleSet> children) {
this.children = children;
}
}
And finally the Demand entity
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
public class Demand extends BaseEntity {
#ManyToOne(optional = false)
private Article article;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable = false)
private Date demandTime;
private double quantity;
public Article getArticle() {
return article;
}
public void setArticle(Article article) {
this.article = article;
}
public Date getTimeStamp() {
return demandTime;
}
public void setTimeStamp(Date demandTime) {
this.demandTime = demandTime;
}
public double getQuantity() {
return quantity;
}
public void setQuantity(double quantity) {
this.quantity = quantity;
}
}
For example there exists an article set with the name "ArticleSetOfTwo" and the number 002 and contains the articles "Article 1" and "Article 2" with the numbers 1 and 2.
Article 1 has the following demand: (Left is date and right is quantity)
07-11-2011, 10
08-11-2011, 50
15-11-2011, 200
15-11-2011, 300
16-11-2011, 100
Article 2 has the following demand:
08-11-2011, 20
09-11-2011, 10
14-11-2011, 150
15-11-2011, 150
16-11-2011, 100
Now I want to sum all quantities in the article set divided by a period of our enum, e.g. week. Then this would be for the Articleset:
For the first week starting at 07-11-2011 until 13-11-2011 it would be: 90
For the second week starting at 14-11-2011 until 20-11-2011 it would be: 1000
These values I'd like to store in a ArrayList but I don't know how to do it. Maybe someone can solve it. Thank you very much in advance!
I'm not sure it's doable using a query.
I would just select all the date/quantity pairs for the article set, ordered by date, and then do a loop starting from the start date and ending with the end date, and add the quantities in Java.
The HQL would look like this:
select d.demandTime, d.quantity from Demand d, ArticleSet set
inner join set.articles article
where d.article = article
order by d.demandTime
Then, for each week, loop through the pairs and, if the demand time is between the start and the end of the week, add the quantity of the demand to the week sum.