OneToMany | Uni directional | (Optional) - gauravsk89/hibernate GitHub Wiki
Scenario:
Optional | OneToMany Unidirectional
In Online bidding system an item can have 0...n bids associated to it. And in this case association is kept as Unidirectional, but in real life in most cases it would be bi-directional (we may want to navigate to the item a bid belongs to).
Since this relation is a Optional one, so on database side a join table has been used to persist the association.
ITEM
ID (PK)
NAME NOT NULL
INITIAL_AMOUNT NOT NULL
SELLER_ID NOT NULL
BID
ID (PK)
AMOUNT NOT NULL
ITEM_BID_REL
ITEM_ID (PK) [FK TO ITEM Table]
BID_ID (PK) [FK TO BID Table]
Entities:
Item entity has a collection reference to Bids
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "ITEM_BID_REL", joinColumns = @JoinColumn(name = "ITEM_ID"),
inverseJoinColumns = @JoinColumn(name = "BID_ID"))
private Set<Bid> bids;
Since this is uni-directional association and that too optional, so Bid entity has no reference back to Item class.
@JoinTable explained:
name : signifies the join table
joinColumns : tells name of the column that should be mapped with PK of this entity (entity inside which @JoinTable is defined)
inverseJoinColumns : tells name of the column that should be mapped with PK of other entity (entity defined with set Set i.e. Bid entity in this case)
So basically these name are not the names of entities, but these are the names of the columns of the Join table.
To test that if we swap the names in annotation like given below. @JoinTable(name = "ITEM_BID_REL", joinColumns = @JoinColumn(name = "BID_ID"), inverseJoinColumns = @JoinColumn(name = "ITEM_ID")) then swapped values will be inserted in database. In this case we have given "BID_ID" in "joinColumns" so what we try to say is that PK of Item entity i.e. ITEM_ID will be inserted into BID_ID column and "ITEM_ID" is given in "inverseJoinColumns" so what we try to say is that PK of inverse entity i.e. ID of Bid entity will be inserted into ITEM_ID column.
A convenience method has been added in Item entity to update the association between the two entities. public void addOrUpdateBids(Bid bid){ if(this.bids == null){ this.bids = new HashSet<>(); } this.getBids().add(bid); }
Persistence Logic:
@Override
@Transactional
public Item addBidToItem(BidDTO bidDTO) {
Item item = itemsRepository.findOne(bidDTO.getItemId());
Bid bid = Bid.builder()
.bidAmount(bidDTO.getAmount())
.build();
item.addOrUpdateBids(bid);
itemsRepository.save(item);
return item;
}