I need to create a M to N mapping, with anotations, for this tables:
Table Food : Columns: id, description, size, type
Table Ingredients: Columns: id, description, price
Table Food_Ingredients: Columns: food_id (FK), ingredient_id (FK), quantity
Classes:
class Food {
/*mapped fields setter/getters*/
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH)
#JoinTable( name = "food_ingredient",
joinColumns = { #JoinColumn(name = "food_id", nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "ingredient_id", nullable = false) })
private List<Ingredient> ingredients;
}
class Ingredients {/*mapped fields setter/getters*/}
So, how can I map those entities?
How are you going to represent the quantity in your model? You should create a new entity for FoodIngredients with this property(and links to both other tables) and map it using #OneToMany annotations in Food and Ingredients.
Edit: You can use http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/ for reference
Related
#ManyToOne
#JoinColumn(name = "someValue" , referencedColumnName = "someOtherValue" )
What values are to be placed in name and referencedColumnName column if 2 tables are linked by ManyToOne association?
Suppose you have Two tables:
1. Department table with columns:
a. Dept_ID (primary key)
b. Dept_Name
2. Employee Table with following column:
a. Emp_Id (primary key)
b. Dept_Id_fk (foreign key)
c. Salary
Now your join column for Employee Entity class will be
#ManyToOne
#JoinColumn(name = "Dept_Id_fk", referencedColumnName = "Dept_ID")
Department department;
So referencedColumnName means column that you are referencing to from your foreign key column.
How would the join column look like for oneToMany association? Here is an example:
Person table:
person_id (pk), person_name
person_reltn table:
person_reltn_id (pk),
child_person_id (fk),
parent_person_id (fk)
For the above tables, if I were to create the Person entity:
class Person(){
#Id
#Column(name = "PERSON_ID")
private long personId;
#NotFound(action = NotFoundAction.IGNORE)
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(
name = "CHILD_PERSON_ID",
referencedColumnName = "PERSON_ID",
updatable = false,
insertable = false)
#Where(clause = "ACTIVE_IND = 1")
#Filter(
name = FilterConstants.END_EFFECTIVE_DATE_TIME_FILTER,
condition = FilterConstants.END_EFFECTIVE_DATE_TIME_CONDITION)
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
private final List<PersonRelation> personRelations = new ArrayList<>();
}
In the joinColumn, should the name always have the foreign key (which means the value from entity you are joining to) and the referenceColumnName should alway have the primary key on the entity? If yes, it will be the opposite of Sayantan's response above. Please let me know if I misunderstood the concept.
Update on 03/04/2021
After doing more research, I found the documentation on how to set the referenceColumnName based on the entity mappings[1]. Looks like, for unidirectional OneToMany mapping, the referenced column is in the table of the source entity.
1.https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumn.html
I am trying to persist a OneToMany parent child relation with Join table, but in insert sql for join table only one column is considered (out of two).
insert into ITEM_BIDS_REL (BID_ID) values (?)
It does not include ITEM_ID column and due to that getting below error.
java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("BIDDING_SYSTEM_OWNER"."ITEM_BIDS_REL"."ITEM_ID")
Two question here:
Why it only includes BID_ID column in INSERT query for ITEM_BIDS_REL join table.
Is the right way to design JOIN TABLE like I have kept BID_ID ad PK,FK and ITEM_ID as FK.
Use case:
Referring the "Online Action (bidding) System" example from Java Persistence with Hibernate book.
An Item can have many Bids on it.
ITEM table
ITEM_ID PK
NAME
INITIAL_AMOUNT
ITEM_BIDS table
BID_ID PK
AMOUNT
ITEM_BIDS_REL Join Table
BID_ID PK (FK from ITEM_BIDS table)
ITEM_ID NOT NULL (FK from ITEM table)
Entity classes:
Item Class
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable( name = "ITEM_BIDS_REL",
joinColumns = #JoinColumn(name = "ITEM_ID"),
inverseJoinColumns = #JoinColumn(name = "BID_ID"))
#JsonIgnore
private Set<Bid> bids;
Bid class
#ManyToOne(cascade = CascadeType.ALL)
#JoinTable(name = "ITEM_BIDS_REL",
joinColumns = {#JoinColumn(name = "BID_ID", insertable = false,
updatable = false)},
inverseJoinColumns = {#JoinColumn(name="ITEM_ID", insertable = false,
updatable = false)})
private Item item;
Persistence logic:
public Item addBid(BidDTO bidDTO) {
Item item = itemsRepository.findOne(bidDTO.getItemId());
Bid bid = Bid.builder()
.item(item)
.bidAmount(bidDTO.getBidAmount())
.build();
if(item.getBids() == null){
item.setBids(new HashSet<>());
}
item.getBids().add(bid);
bidRepository.save(bid);
itemsRepository.save(item);
return item;
}
How can I use #JoinTable to join three tables?
I have three tables:
user:
id, name
post:
id, date
company:
id, name
I want to create a new table with the following columns:
user_id, post_id, company_id.
I used:
#JoinTable(name = "new_table", joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "post_id"))
However, I am not sure how to add the third column.
You must not will use #JoinTable annotation. The #JoinTable annotation is used only to #ManyToMany relationship.
You need create a new Entity with three field, and each field must has the #ManyToOne and #JoinColumn annotation.
For Instance:
#Entity
#Table(name = "table_name")
class NewEntity {
//Id and anothers fields
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#ManyToOne
#JoinColumn(name = "post_id")
private Post post;
#ManyToOne
#JoinColumn(name = "company_id")
private Company company;
//getters and setters
}
I'm using spring jpa.
I have the following entity:
public class CountryParameter extends Parameter {
#ElementCollection(targetClass = Country.class)
#CollectionTable(name = "Parameter_Countries", joinColumns = #JoinColumn(name = "segmentParameter_id"))
#Column(name = "country")
#Enumerated(EnumType.STRING)
private Set<Country> countries;
Edit: country is en enum.
The collection table has only 2 columns: parameter_id and country, I would like to add more like id.
how can I do this?
Given 3 tables:
student (id)
student_to_class (student_id, class_id)
class (id)
I'd like to apply a where clause on the student_to_class where student_id = :studentId. I've found many examples that apply where clause on "class" table or "student" table, but not the many-to-many table.
The student table has a #ManyToMany
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(
name = "student_to_class",
joinColumns = { #JoinColumn(name = "student_id", nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "class_id", nullable = false) }
)
private Set<ClassEntity> classes;
The class table has a #ManyToMany
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(
name = "student_to_class",
joinColumns = { #JoinColumn(name = "class_id", nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "student_id", nullable = false) }
)
private Set<StudentEntity> students;
Here is the query I'm trying to translate into Criteria:
select * from student, student_to_class where student_to_class.student_id = 1 and student.id = student_to_class.class_id
I'm trying to figure out how to reference the many-to-many table since I don't have an actual class representing this table.
Criteria c = sessionFactory.getCurrentSession().createCriteria(ClassEntity.class);
c.createAlias("student_to_class", "entities"); // how to reference the student_to_class ?
c.add(Restrictions.eq("entities.user_id", studentEntity.getId()));
But I get an error, which makes sense to me, but I haven't had much luck fixing it:
could not resolve property: student_to_class
Since the studentid in the Student table will be the same as the studentid in the student_to_class table there is no need to filter by the join table. Simply run the where clause against student.student_id