I just get started with JPA. I have an entity CustomerOrderEntity which has #OneToMany relation with another entity BeverageEntity. When I add the BeverageEntity to the CustomerOrderEntity a new entity is created of the type BeverageEntity and is persisted in the database as a new record. I do not want something like that I only need the CustomerOrderEntity to have the record of BeverageEntity and a new entity is not created for that inside the database.
These two entities are invoked from this class SalesManagement:
#Stateless
#Remote(SalesManagement.class)
public class SalesManagementBean implements SalesManagement {
#PersistenceContext(type = PersistenceContextType.TRANSACTION)
EntityManager em;
#Override
public void createOrder(CustomerOrder order) {
order.getOrderItems().forEach(item -> {
updateBeverageQuantity(item.getId(), item.getQuantity());
});
CustomerOrderEntity customerOrderEntity = new CustomerOrderEntity();
customerOrderEntity.setIssueDate(order.getIssueDate());
order.getOrderItems().forEach(item ->{
customerOrderEntity.addOrder(toEntity(item));
});
em.persist(customerOrderEntity);
}
public void updateBeverageQuantity(int b_id, int quantity) {
BeverageEntity beverageEntity = em.find(BeverageEntity.class, b_id);
if(beverageEntity != null) {
beverageEntity.setQuantity(beverageEntity.getQuantity() - quantity);
em.persist(beverageEntity);
}
}
public List<BeverageEntity> toBeverageEntity(List<Beverage> beverages) {
List<BeverageEntity> entities = new ArrayList<BeverageEntity>();
if(beverages != null && beverages.size() > 0) {
beverages.forEach(beverage -> {
BeverageEntity entity = new BeverageEntity();
entity.setName(beverage.getName());
entity.setManufacturer(beverage.getManufacturer());
entity.setQuantity(beverage.getQuantity());
entity.setPrice(beverage.getPrice());
entity.setIncentiveEntity(toIncentiveEntity(beverage.getIncentiveDTO()));
entities.add(entity);
});
return entities;
}
return null;
}
public IncentiveEntity toIncentiveEntity(IncentiveDTO incentiveDTO) {
if(incentiveDTO != null) {
IncentiveEntity entity = null;
return entity;
}
return null;
}
public BeverageEntity toEntity(Beverage b) {
BeverageEntity entity = new BeverageEntity();
entity.setName(b.getName());
entity.setManufacturer(b.getManufacturer());
entity.setQuantity(b.getQuantity());
entity.setPrice(b.getPrice());
entity.setIncentiveEntity(toIncentiveEntity(b.getIncentiveDTO()));
return entity;
}
}
I think the problem is in the method toBeverageEntity. But I am not sure about it.
The CustomerOrderEntity:
#Entity
public class CustomerOrderEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
#Version
private int version;
private Date issueDate;
#OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private List<BeverageEntity> beverageEntities;
public void addOrder(BeverageEntity beverageEntity) {
this.beverageEntities.add(beverageEntity);
}
public List<BeverageEntity> getBeverageEntities() {
return beverageEntities;
}
public void setBeverageEntities(List<BeverageEntity> beverageEntities) {
this.beverageEntities = beverageEntities;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Date getIssueDate() {
return issueDate;
}
public void setIssueDate(Date issueDate) {
this.issueDate = issueDate;
}
}
The BeverageEntity:
#Entity
public class BeverageEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String name;
private String manufacturer;
private int quantity;
private double price;
#Version
private int version;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private IncentiveEntity incentiveEntity;
public BeverageEntity() {
}
public BeverageEntity(String name, String manufacturer, int quantity, Double price, IncentiveEntity entity) {
this.name = name;
this.manufacturer = manufacturer;
this.quantity = quantity;
this.price = price;
this.incentiveEntity = entity;
}
public BeverageEntity(String name, String manufacturer, int quantity, Double price) {
this.name = name;
this.manufacturer = manufacturer;
this.quantity = quantity;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public IncentiveEntity getIncentiveEntity() {
return incentiveEntity;
}
public void setIncentiveEntity(IncentiveEntity incentiveEntity) {
this.incentiveEntity = incentiveEntity;
}
}
Found the problem it was in the method toBeverageEntity as pointed out in the comments I was creating a new entity that was wrong. I needed to use find because the entity is already in the database.
BeverageEntity entity = em.find(BeverageEntity.class, beverage.getId());
entities.add(entity);
Related
Here is my entity class
#Entity
#Table( name = "NEO_TEAM", schema = "METRICS" )
public class ETeam implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private int id;
#Column(name="NAME")
private String name;
#Column(name="DESCRIPTION")
private String description;
//bi-directional many-to-one association to ETeamQueue
#OneToMany(mappedBy="eteam" , fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<ETeamQueue> teamQueue;
public ETeam(int id,String name,String description){
this.id = id;
this.name = name;
this.description = description;
}
public ETeam(String name,String description){
this.name = name;
this.description = description;
}
public ETeam() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public List<ETeamQueue> getTeamQueue() {
return this.teamQueue;
}
public void setTeamQueue(List<ETeamQueue> teamQueue) {
this.teamQueue = teamQueue;
}
public ETeamQueue addTeamQueue(ETeamQueue teamQueue) {
getTeamQueue().add(teamQueue);
teamQueue.setEteam(this);
return teamQueue;
}
public ETeamQueue removeTeamQueue(ETeamQueue teamQueue) {
getTeamQueue().remove(teamQueue);
teamQueue.setEteam(null);
return teamQueue;
}
}
And My REST call and JPQL query is
#Path("team")
#Produces(MediaType.APPLICATION_JSON)
public class TeamResource {
TeamService ts = new TeamService();
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public List<ETeam> listTeam(#PathParam("id") int id){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("NeoMetrics");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select e from ETeam e where e.id = :id ",ETeam.class);
query.setParameter("id", id);
List<ETeam> lis = (List<ETeam>) query.getResultList();
//List<ETeam> lis = ts.getTeam(id);
return lis;
}
i want to fetch only one record from the team table but it give me result like shown in picture , which show the result is looped thousand times , its very long output result i only put part of it , any help will be really appreciated
i have a rellationship between 2 classes Document and Medecin
#Entity
public class Document implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String annee;
private Date dateVisite;
private String secteur;
private String typeVisite;
#OneToOne( fetch=FetchType.LAZY,cascade=CascadeType.REMOVE)
#JoinColumn(name = "idMedecin")
private Medecin medecin;
public Document(String annee,
Date dateVisite, String secteur, String typeVisite) {
super();
this.annee = annee;
this.dateVisite = dateVisite;
this.secteur = secteur;
this.typeVisite = typeVisite;
}
public String getSecteur() {
return secteur;
}
public void setSecteur(String secteur) {
this.secteur = secteur;
}
public String getTypeVisite() {
return typeVisite;
}
public void setTypeVisite(String typeVisite) {
this.typeVisite = typeVisite;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAnnee() {
return annee;
}
public void setAnnee(String annee) {
this.annee = annee;
}
public Date getDateVisite() {
return dateVisite;
}
public void setDateVisite(Date dateVisite) {
this.dateVisite = dateVisite;
}
}
and the medecin entity is
#Entity
public class Medecin implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String nom;
private String secteur;
private int telephone;
private int specialite;
public Medecin() {
super();
// TODO Auto-generated constructor stub
}
public Medecin(String nom, String secteur, int telephone, int specialite) {
super();
this.nom = nom;
this.secteur = secteur;
this.telephone = telephone;
this.specialite = specialite;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getSecteur() {
return secteur;
}
public void setSecteur(String secteur) {
this.secteur = secteur;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSpecialite() {
return specialite;
}
public void setSpecialite(int specialite) {
this.specialite = specialite;
}
}
the problem is that after i generate the database i want if i delete the document record from the database i want the medecin record will be deleted also but in my case if i delete the document record the medecin record dont be deleted
Based on your configuration, Hibernate will generate Document table with foreign key pointing to Medicine table.
To achieve your requirement, it should be like:
public class Document {
#OneToOne(mappedBy = "document", cascade = CascadeType.REMOVE)
private Medicine medicine;
}
public class Medicine {
#OneToOne
private Document document;
}
Updated
public void delete(int id){
Document document = entityManager.find(Document.class, id);
entityManager.remove(document);
entityManager.flush();
}
I have three entities, Trader, Portfolio and Member. Each Trader has a Portfolio and a Portfolio can have many Members. I have set up the following relationships. I'm not sure how to use the Jointable that is created, i.e. Portfolio_PORTFOLIOID and members_MEMBERID. Obviously I'd like to associate each portfolid with member id's, however I'm not sure how to go about this. How is the jointable data persisted?
My Portfolio class
#Entity
#Table(name="Portfolio")
#NamedQuery(
name="findPortfolioByTrader",
query="SELECT p FROM Portfolio p" +
" WHERE Trader = :trader"
)
public class Portfolio {
#Id
#GeneratedValue
private Integer portfolioId;
#Temporal(TIMESTAMP)
private Date lastUpdate;
private Integer balance;
private Trader trader;
private Collection<Member> members;
public Portfolio() {
this.lastUpdate = new Date();
}
public Portfolio(Integer balance, Trader trader) {
this.lastUpdate = new Date();
this.balance = balance;
this.trader = trader;
}
public Integer getPortfolioId() {
return portfolioId;
}
public void setPortfolioId(Integer portfolioId) {
this.portfolioId = portfolioId;
}
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
#ManyToMany
#JoinTable(
name="MEMBER_PORTFOLIO",
joinColumns=
#JoinColumn(name="Member_MEMBERID", referencedColumnName="MEMBERID"),
inverseJoinColumns=
#JoinColumn(name="portfolio_PORTFOLIOID", referencedColumnName="PORTFOLIOID")
)
public Collection<Member> getMembers() {
return members;
}
public void setMembers(Collection<Member> members) {
this.members = members;
}
#OneToOne(cascade=ALL, mappedBy="portfolio")
public Trader getTrader()
{
return trader;
}
public void setTrader(Trader trader)
{
this.trader = trader;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
}
My Member class
#Entity
#Table(name="Member")
#NamedQuery(
name="findAllMembers",
query="SELECT m FROM Member m " +
"ORDER BY m.memberId"
)
public class Member implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -468520665316481235L;
private String memberId;
private String forename;
private String surname;
private Integer position;
private Integer majority;
private Integer IPO;
private Integer questions;
private Integer answers;
private Party party;
private Date lastUpdate;
private char status;
private Collection<Portfolio> portfolios;
private Collection<AskOrder> askOrders;
private Collection<BidOrder> bidOrders;
public Member() {
this.lastUpdate = new Date();
}
public Member(String memberId,String forename, String surname, Integer position,
Integer majority, Integer IPO, Integer questions, Integer answers, Party party) {
this.memberId = memberId;
this.forename = forename;
this.surname = surname;
this.position = position;
this.majority = majority;
this.IPO = IPO;
this.questions = questions;
this.answers = answers;
this.party = party;
this.lastUpdate = new Date();
this.askOrders = new ArrayList<AskOrder>();
this.bidOrders = new ArrayList<BidOrder>();
this.portfolios = new ArrayList<Portfolio>();
}
#Id
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public char getStatus() {
return status;
}
public void setStatus(char status) {
this.status = status;
}
#Temporal(TIMESTAMP)
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getForename()
{
return forename;
}
public void setForename(String forename)
{
this.forename = forename;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
public Integer getMajority() {
return majority;
}
public void setMajority(Integer majority) {
this.majority = majority;
}
public Integer getIPO() {
return IPO;
}
public void setIPO(Integer iPO) {
IPO = iPO;
}
public Integer getQuestions() {
return questions;
}
public void setQuestions(Integer questions) {
this.questions = questions;
}
public Integer getAnswers() {
return answers;
}
public void setAnswers(Integer answers) {
this.answers = answers;
}
#ManyToOne
public Party getParty() {
return party;
}
public void setParty(Party party) {
this.party = party;
}
#OneToMany(cascade=ALL, mappedBy="member")
public Collection<AskOrder> getAskOrders()
{
return askOrders;
}
public void setAskOrders(Collection<AskOrder> orders)
{
this.askOrders = orders;
}
#OneToMany(cascade=ALL, mappedBy="member")
public Collection<BidOrder> getBidOrders()
{
return bidOrders;
}
public void setBidOrders(Collection<BidOrder> bidOrders)
{
this.bidOrders = bidOrders;
}
#ManyToMany //FIXME should probably be many to many - done
public Collection<Portfolio> getPortfolios() {
return portfolios;
}
public void setPortfolios(Collection<Portfolio> portfolios) {
this.portfolios = portfolios;
}
}
#Entity
public class Portfolio
{
#Id
#GeneratedValue
private int id;
#ManyToMany
#JoinTable( name = "PortfolioMember",
#JoinColumns : #JoinColumn( name = "Portfolio_ID", referencedColumnName="id" ),
#InverseJoinColumns : #JoinColumn( name = "Member_ID", referencedColumnName="id" )
)
private List<Member> members;
}
#Entity
public class Member
{
#Id
#GeneratedValue
private int id;
#ManyToMany( mappedBy = members )
private List<Portfolio> portfolios;
}
I'm using Spring data jpa and i am trying to do this :
#RequestMapping(value = "/setview/{id}", method = RequestMethod.GET)
public Iterable<Task> setView(#PathVariable Integer id) {
System.out.println("setViewTrue -------------------");
Iterable<Task> tasks = taskRepository.findByUserId(id);
for (Task t : tasks) {
t.setView(true);
taskRepository.save(t);
System.out.println("task****: "+ t.isView());
}
return tasks;
}
but i got this error:
[Ljava.lang.Object; cannot be cast to com.yess.erp.crm.domain.Task
i just want to loop an iterbale of tasks and change the value of a boolean(false) to true.
this is my Task.java:
#Entity
public class Task implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "pk_sequence", sequenceName = "task_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence")
private Integer id;
#NotEmpty
private String title;
#Lob
private byte[] image;
private Date created_at;
private Date start_date;
private Date end_date;
private String description;
private boolean view;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
private User user;
public Task() {
}
public Task(String title, User user) {
super();
this.title = title;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public Date getStart_date() {
return start_date;
}
public void setStart_date(Date start_date) {
this.start_date = start_date;
}
public Date getEnd_date() {
return end_date;
}
public void setEnd_date(Date end_date) {
this.end_date = end_date;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isView() {
return view;
}
public void setView(boolean view) {
this.view = view;
}
}
this is my TaskRepository.java:
public interface TaskRepository extends CrudRepository<Task, Integer> {
#Query("from Task as t inner join t.user as u where u.id = :id AND t.view = false")
Iterable<Task> findByUserId(#Param("id") Integer id);
}
this is my TaskController.java:
#RestController
#RequestMapping("/tasks")
public class TaskController {
#Autowired
private TaskRepository taskRepository;
.
.
.
#RequestMapping(value = "/setview/{id}", method = RequestMethod.GET)
public Iterable<Task> setView(#PathVariable Integer id) {
System.out.println("setViewTrue -------------------");
Iterable<Task> tasks = taskRepository.findByUserId(id);
for (Task t : tasks) {
t.setView(true);
taskRepository.save(t);
System.out.println("task****: "+ t.isView());
}
return tasks;
}
}
Your query isn't returning just a task, it is likely returning a task and user, in an Object[] array.
You might be able to alter your query to get a Task back. I'm thinking SELECT t FROM Task t...
I have a One-to-Many relationship: A ProductCategory can contains many Product. This is the code:
#Entity
public class Product implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private String id;
#Column(name="ProductName")
private String name;
private BigDecimal price;
private String description;
#ManyToOne
#JoinColumn(name="UserId")
private User user;
#ManyToOne
#JoinColumn(name="Category")
private ProductCategory category;
private static final long serialVersionUID = 1L;
public Product() {
super();
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return this.price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public ProductCategory getCategory() {
return this.category;
}
public void setCategory(ProductCategory category) {
this.category = category;
}
}
#Entity
public class ProductCategory {
#Id
private String categoryName;
#OneToMany(cascade= CascadeType.ALL,mappedBy="category")
private List<Product> products;
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String productName) {
this.categoryName = productName;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
This is Servlet code which use the 2 entities:
String name = request.getParameter("name");
BigDecimal price = new BigDecimal(request.getParameter("price"));
String description = request.getParameter("description");
ProductCategory category = new ProductCategory();
category.setCategoryName(request.getParameter("category"));
Product product = new Product();
product.setName(name);
product.setPrice(price);
product.setDescription(description);
product.setCategory(category);
User user = userManager.findUser("Meow");
product.setUser(user);
productManager.createProduct(product); // productManager is an EJB injected by container
And this is the error:
java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST
Why does this error happen? I marked the field as "cascade = CascadeType.All"!
You're trying to save a product. And this product is linked to a category. So when JPA saves the product, its category must already exist, or there must be a cascade configured so that persisting the product cascades to persisting its category.
But you don't have such a cascade. What you have is a cascade saying that any operation done on a category cascades to its list of products.