In my code i have a oneToMany relation between customer class and item class. This means that, a customer may have one or many items.
Here is the customer code:
#Entity
#Data
public class customer {
#Id
#GeneratedValue
int id;
String name;
String lastname;
#Embedded
Address address;
#OneToMany
#Column(name="ITEM_ID")
List<item> item;
}
and it's the item class:
#Entity
#Data
public class item {
#Id
#GeneratedValue
int id;
String name;
String Serialnumber;
int price;
#ManyToOne
customer customer;
}
Then i have made some tests to try my queries in the models.
insert into item(id,name,Serialnumber,price) values(1,'bike','123',200);
insert into item(id,name,Serialnumber,price) values(2,'car','123',200);
insert into customer(id,name,lastname,Country,City,Street,No,item_id)
values(1,'Salman','Lashkarara','Iran','Tehran','Shariati','12',1);
insert into customer(id,name,lastname,Country,City,Street,No,item_id)
values(2,'Saba','Lashkarara','Iran','Tehran','Shariati','12',2);
insert into customer(id,name,lastname,Country,City,Street,No,item_id)
values(3,'Saba','Lashkarara','Iran','Tehran','Shariati','12',1);
But when i run my code, i face with the following error:
Column "ITEM_ID" not found; SQL statement:
insert into customer(id,name,lastname,Country,City,Street,No,item_id) values(1,'Salman','Lashkarara','Iran','Tehran','Shariati','12',1)
Please pay especial attention, that it is a java mvc-spring application and i create my models using the code, so there is no database to check the field item_id.
As you can see i have already added the #Column(name="ITEM_ID") to define the column.
You have to use #JoinColumn for association columns:
#OneToMany
#JoinColumn(name="ITEM_ID")
List<item> item;
some other options
#OneToMany(cascade=CascadeType.All, fetch=FetchType.EAGER)
#JoinColumn(name="ITEM_ID")
List<item> item;
in Item class
#ManyToOne(mappedBy="item")
customer customer;
you could do this i also have user class and bcr class, one user have many bcr so below code will help you
bcr.java
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_who_enter_demand", nullable = false)
public User getUserByUserWhoEnterDemand() {
return this.userByUserWhoEnterDemand;
}
public void setUserByUserWhoEnterDemand(User userByUserWhoEnterDemand) {
this.userByUserWhoEnterDemand = userByUserWhoEnterDemand;
}
user.java
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userByUserWhoEnterDemand")
public Set<BudgetControlRegister> getBudgetControlRegistersForUserWhoEnterDemand() {
return this.budgetControlRegistersForUserWhoEnterDemand;
}
public void setBudgetControlRegistersForUserWhoEnterDemand(Set<BudgetControlRegister> budgetControlRegistersForUserWhoEnterDemand) {
this.budgetControlRegistersForUserWhoEnterDemand = budgetControlRegistersForUserWhoEnterDemand;
}
You can't map a table column without table:
#Entity
#Table(name = "ITEM_TABLE")
public class item {
...
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name = "CUSTOMER_ID_ITEM_TABLE")
private customer customer;
...
}
#Entity
#Table(name = "CUSTOMER_TABLE")
public class customer {
...
#OneToMany
#Column(name="ITEM_ID")
List<item> item;
}
Related
I am working a very small application which contains 3 entity classes.
1.Category.
2.Products.
3.User
Relationships:-
a. OneToMany between User and Products.
b. OneToMany and ManyToOne between category and products i.e. a category can have multiple products and multiple products can belong to same category.
Entity Classes are shown below:-
User Entity:-
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String lastname;
private String email;
private String password;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.EAGER)
private Set<Products> products;
//getter and setter
}
Products Entity:-
#Entity
public class Products {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String productname;
private String cost;
#ManyToOne(cascade = {CascadeType.MERGE,CascadeType.PERSIST},
fetch = FetchType.LAZY)
private Category category;
//getter and setters
}
Category Entity:-
#Entity
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(mappedBy = "category",
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.EAGER)
private List<Products> products;
//getter and setters
}
Method to merge User with products in data base:-
#GetMapping("/cart")
public String Cart(Model model){
model.addAttribute("cart",productsSet);
System.out.println(productsSet);//At this stage in console I am able to see products added in set
User user = userRepository.findById(1);//hard coded for now.
user.setProducts(productsSet);
userService.saveUserProducts(user);//saveUserProducts() method in shown below.
productsSet.clear();
return "mycart";
}
saveUserProducts() :-
#Override
#Transactional
public void saveUserProducts(User user) {
entityManager.merge(user);
}
But when I am running the program I see the following exception in console:-
java.lang.IllegalStateException: Multiple representations of the same entity [com.demo.shopping.com.Entity.Products#2] are being merged. Detached: [Products{id=2, productname='p2', cost='200'}]; Detached: [Products{id=2, productname='p2', cost='200'}]
I found an article on stack-overflow but it was not fit in my situation.(java.lang.IllegalStateException: Multiple representations of the same entity with #ManyToMany 3 entities).Except this I don't get any relevant thing.
Please help me to let me know how to deal with this situation. Hope someone will help.
Thanks in advance.
Remove CascadeType.MERGE user class because in my program I am not adding new products also except this I am creating relation between existing user and products.
OK, so I've designed a basic CRUD an an exercise. It has 2 tables Jobs and Employees. I'm trying to create a many to one relationship, but when I click the link to go to the Employee Entry page it throws an error that kicks off with the #ManyToOne referencing an Unknown Entity.
Here is what I've got in my Employees.java
String jobName;
#ManyToOne(fetch=FetchType.EAGER)
#Fetch(value = FetchMode.JOIN)
#JoinColumn(name = "Job_Name")
#Column (name='jobName')
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
Any idea what i"m doing wrong and how to resolve this?
As per your comment,i think you can define relationship between these two entities like below.
#Entity
#Table(name="employee")
class Employee{
#Id
#GeneratedValue
private Integer id;
#ManyToOne
#JoinColumn(name = "job_name")
private Job job;
// other column and getter and setter
}
#Entity
#Table(name="job")
class Job{
#Id
#GeneratedValue
private Integer id;
#Column(name="job_name")
private String jobName;
//provide other column and getter setter
}
I've done the necessary changes to my models outlined here. However, I don't know what to put on my join table entity.
Note that my join table has a surrogate key , and two extra columns (date and varchar).
What I've got so far is:
User.java
#Entity
#Table (name = "tbl_bo_gui_user")
#DynamicInsert
#DynamicUpdate
public class User implements Serializable {
private String id;
private String ntName;
private String email;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
Group.java
#Entity
#Table (name = "tbl_bo_gui_group")
#DynamicInsert
#DynamicUpdate
public class Group implements Serializable {
private String id;
private String groupName;
private String groupDesc;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.group", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
The problem is that I don't know what to put on my join table entity. Here it is.
GroupUser.java
#Entity
#Table (name = "tbl_bo_gui_group_user")
#DynamicInsert
#DynamicUpdate
#AssociationOverrides({
#AssociationOverride(name = "pk.user",
joinColumns = #JoinColumn(name = "id")),
#AssociationOverride(name = "pk.group",
joinColumns = #JoinColumn(name = "id")) })
public class GroupUser implements Serializable {
private String id;
private User userId;
private Group groupId;
private Date dateCreated;
private String createdBy;
// constructors and getters and setters for each property
// What now? ? No idea
}
user to group would be a Many-To-Many relation. Now, you are splitting that up into Two One-To-Many Relations. Therefore your Mapping Entity simple needs to complete the Many-To-Many relation, by using Many-To-One:
public class GroupUser implements Serializable {
private String id;
#ManyToOne
private User userId;
#ManyToOne
private Group groupId;
private Date dateCreated;
private String createdBy;
}
See also this example: Mapping many-to-many association table with extra column(s) (The Answer with 38 upvotes)
I've read many tutorials about spring-hibernate relationships but I'm a bit confused about how to use them in my case... I've product/category entities defined as follow:
Product
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#Column
private int category;
.
.
.
Category
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#NotEmpty
#Column
#Size (max = 25)
private String name;
.
.
.
So, I'd like in the product list page, under the voice "category" would appear the category name, and in the product form the category list...
In my case a product fits only one category so if I'm right it should be a #ManyToOne but I don't know how to implement this... in my product database I've the categoryId field, but if I mark the category entity field as #OneToMany it will not be stored to the db...
EDIT
I've changed like this (as suggested):
Product.class
#Table(name = "products")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#NotEmpty
#Column
#Size (max = 25)
private String name;
#Column
#Size (max = 255)
private String description;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "category_id", nullable = false)
private Category category;
Category.class
#Entity
#Table(name = "categories")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#NotEmpty
#Column
#Size (max = 25)
private String name;
#Column
#Size (max = 255)
private String description;
//Here mappedBy indicates that the owner is in the other side
#OneToMany(fetch = FetchType.EAGER, mappedBy = "category", cascade = CascadeType.ALL)
private Set<Product> products = new HashSet<Product>();
Controller
#RequestMapping(value = "/add/", method = RequestMethod.POST)
public String addProduct(
#ModelAttribute(value = "product") #Valid Product product,
BindingResult result, ModelMap model, Category category) {
if (result.hasErrors()) {
return "forms/productForm";
}
try {
category.addProduct(product);
product.setCategory(category);
// Add product to db
productService.addProduct(product);
} catch (Exception e) {
log.error("/add/---" + e);
return "redirect:/product/deniedAction/?code=0";
}
return "redirect:/admin/product/";
}
I also added a #initbinder on the product controller to translate the data from the product form string to Category... but now when I save a product it automatically saves a category instead of attach the existing selected one...
As the Product will have only one Category and Category will have a list of Products, you can relate these two by creating a Foreign Key in the Product table to refer to the primary key in the Category table:
Category Table: id, name, other fields...
Product Table: id, category_id (FK), and other fields.
And the mapping can be defined as below:
public class Category {
//Here mappedBy indicates that the owner is in the other side
#OneToMany(fetch = FetchType.LAZY, mappedBy = "category", cascade = CascadeType.ALL)
private Set<Product> products = new HashSet<Product>();
...
}
public class Product {
//Here JoinColumn states that this entity is the owner of the relationship
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category_id", nullable = false)
private Category category;
...
}
The mappedBy attribute tells Hibernate that the collection is a mirror image of the many-to-one association on the other side. Its like telling Hibernate that it should propagate changes made at the Product end of the association to the database, ignoring changes made only to the products collection that you have in the Category. Thus if we only call category.getProducts().add(product), no changes will be made persistent. As the association is bidirectional, you have to create the link on two sides, not just one.
For your convenience, you can add one addProduct method in the Category class to save the association:
public void addProduct(Product product) {
product.setCategory(this);
products.add(product);
}
You appear to have a one-to-many relationship between Category and Product (one category has many products)
In Java (and OO generally) you'd expect the Category class to contain a list of Products, so the Category can be said to 'own' products.
In SQL it's the other way round - you'd expect Product table to hold a foreign key reference to a Category, so here, the Product can be said to 'own' a Category.
Looks like your using JPA, so you could have something like this:
Category class:
#Entity
public class Category {
//other stuff...
#OneToMany(cascade=CascadeType.ALL, mappedBy="category")
private Set<Product> products;
}
Product class:
#Entity
public class Product {
//other stuff...
#ManyToOne
private Category category;
}
so you have this:
Product{
atributtes...
#ManyToOne
Category category; --so every product has a category
}
Category {
attributtes...
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="id_Product")
private List<Product> products;
}
try this, if not we can look another solution..
You are right, you should use #ManyToOne because "...a product fits only one category...".
In Product entity declare a Category field instead of int category and annotate it with #ManyToOne. Also add #JoinColumn to specify the name of product.category_id column in the database.
Product:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
.
.
.
I am learning Hibernate ORM(v. 3 ) now and I've a got a question.
I have a table called USERS, created with annotations :
package com.hibernatedb.entities;
import javax.persistence.*;
#Entity
#Table(name = "USERS",uniqueConstraints = {#UniqueConstraint(columnNames={"USER_LOGIN", "USER_EMAIL"})})
public class User {
#Column(name = "USER_LOGIN", length=80, nullable=false)
private String login;
#Column(name = "USER_PASS", length=80, nullable=false)
private String password;
#Column(name = "USER_EMAIL", length=80, nullable=false)
private String email;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "USER_ID", nullable=false)
private Long id;
...
// some getters and setters, toString() and other stuff
...
}
And a Product entity :
#Entity
#Table(name = "PRODUCTS",uniqueConstraints = {#UniqueConstraint(columnNames={"PRODUCT_ID", "PRODUCT_NAME"})})
public class Product {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="PRODUCT_ID")
private long id;
#Column(name="PRODUCT_NAME", length=85, nullable=false)
private String name;
#Column(name="PRODUCT_DESCRIPTION", columnDefinition="mediumtext", length=1000)
private String description;
#Column(name="PRODUCT_COST", nullable=false)
private double cost;
So my question is : How can a create a table called like "USER +
User.getId()
BUYS", which contains a 2 foreign keys (USER_ID and PRODUCT_ID) for user in entity (table record) "User" without raw SQL table creation, but using Hibernate annotations or XML mapping.So i want to have something like
public class TransactionEntityBulider() {
public TransactionEntityBulder(User user)
// something that build me "USER + User.getId() BUYS" table and
}
public TransactionEntity getEntity() {
// something that return a "USER + User.getId() BUYS" table entity
}
Also i would like to see some another ways to solve my problem.
I think hibernate is not done for that kind of usage, because you would have to use dynamic mappings. Hibernate provide ways to specify mapping statically (xml and annotations).
I suggest you modify your approach. It normally should not be harmfull to have all the "USER_BUY" in the same table. Example :
#Entity
public class User {
...
#OneToMany(cascade=CascadeType.ALL, mappedBy="user")
List<UserBuys> buys = new ArrayList<UserBuys>();
...
}
#Entity
public class Product { ... }
#Entity
public class UserBuys {
...
#ManyToOne
Product product;
#ManyToOne
User user;
}