OneToMany | Bi directional | (Non Optional) - gauravsk89/hibernate GitHub Wiki
@Override
@Transactional(value = "transactionManager", readOnly = true) public Set<Bid> getBidsForItem(Long itemId) {
Item item = itemsRepository.findOne(itemId);
if(item != null && item.getBids() != null){ item.getBids().size(); return item.getBids(); }
return null; }
@Override
@Transactional public Item addBid(BidDTO bidDTO) {
Item item = itemsRepository.findOne(bidDTO.getItemId());
Bid bid = Bid.builder() .item(item) .bidAmount(bidDTO.getBidAmount()) .build();
item.addOrUpdateRelation(bid);
itemsRepository.save(item);
return item; }
addOrUpdateRelation(Bid bid){
if(this.bids == null){ this.bids = new HashSet<>(); } this.bids.add(bid); }
To fetch the child entities following needs to be done: 1. at method level add @Transactional(readOnly = true) 2. call item.getBids().size(); so that child list is fetched
alternates: 1. use fetch strategy = FetchType.EAGER or
It does not fetch child list and throws exception if I only call item.getBids(); I think this call should lazily load the child list but that is not the case. Reason below :
Once you leave this @Transactional method
The TransactionManager commits/rollsback the transaction and closes the session. As such, for any entities that were lazy loaded, the Session object that was attached is either null or is closed. Those entities cannot therefore be loaded and hibernate throws an Exception. You will need to either put a broader Session scope, possibly with an OpenSessionInViewFilter, eagerly load your entities, or force some of their initializations (the ones you need) inside the @Transactional method.
@Entity @Table(name = "ITEMS") @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(of = {"itemId", "name"}, callSuper = false) @ToString public class Item {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ITEM_ID_SEQ") @SequenceGenerator(name= "ITEM_ID_SEQ", sequenceName="ITEM_ID_SEQ", allocationSize = 1) @Column(name = "ITEM_ID") @JsonIgnore private Long itemId;
@Column(name = "NAME") private String name;
@Column(name = "INITIAL_AMOUNT") private BigDecimal initialAmount;
@OneToMany(mappedBy = "item", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JsonIgnore private Set<Bid> bids;
public void addOrUpdateRelation(Bid bid){ if(this.bids == null){ this.bids = new HashSet<>(); } this.bids.add(bid); }
}
@Entity @Table(name = "ITEM_BIDS") //@IdClass(Bid.BidPK.class) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = false, of = {"bidId", "itemId"}) public class Bid {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BID_ID_SEQ") @SequenceGenerator(name= "BID_ID_SEQ", sequenceName="BID_ID_SEQ", allocationSize = 1) @Column(name = "BID_ID") private Long bidId;
@Column(name = "AMOUNT") private BigDecimal bidAmount;
@ManyToOne(targetEntity = Item.class) @JoinColumn(name = "ITEM_ID", nullable = false)
// @JsonIgnore
private Item item;
}