I have one Product
entity which has @OneToMany
relationship with Distributor
entity. Now, these Distributor
entities are linked with other Product
entities as well.
Eg Product1
is having Distributor1
, Distributor2
and Distributor3
as children. And Product2
is having Distributor1
, Distributor2
as children.
Now, my requirement is to fetch distributors of each product. Now, due to some data issue, Distributor3
entity got deleted from Database. Hence, when we were initializing the Distributor
entities of Product1
, we got the exception as javax.persistence.EntityNotFoundException: Unable to find com.comapny.Distributor with id xx
which is fine.
However, due to this error, it did not initialize the Distributor
entities of Product2
properly. By not initialzing, I mean, hibernate did create pojo for those entities but did not assign values from DB and hence all values were null. As a result, we received null values for all the fields of Distributor1
and Distributor2
My thought process is, hibernate did create empty entities while initializing them for Product1
but since we got an exception there, it might not have initialized them properly but empty entities remained in hibernate session. And then while initializing them for Product2
, hibernate found them in the session and hence did not care querying them from DB.
Questions:
Code snippets: Product.java
@Entity
@Data
public class Product{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id", nullable = false)
protected Long id;
@JoinTable
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Set<Distributor> distributors = new HashSet<>();
}
Distributor.java
@Entity
@Data
public class Distributor{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id", nullable = false)
protected Long id;
public String distributorName;
}
MyController.java
@RestController
public class MyController extends BaseController {
@Autowired
private MyService myService;
@RequestMapping(value = { "/resources/products"}, method = RequestMethod.GET)
public List<MyResponse> getproductDistributors(@RequestParam(required = true) List<Long> productIds){
// Input received as 2 products. i.e. `Product1` and `Product2`.
List<Product> allProducts = new ArrayList<>();
productIds.forEach(id->{
Product prod = myService.getFullProduct(id);
if(prod!=null)
allProducts.add(prod);
});
// Here, I checked that distributor of `Product2` were initialized to null values.
//Populate MyResponse and return
}
}
MyService.java
@Service
public class MyService {
//Autowire dependencies
@Transactional(readOnly = true)
public Product getFullProduct(Long productId) {
Product product = productRepository.findById(productId);
try{
Hibernate.initialize(product.getDistributors());
} catch(Exception e){
// Exception if any distributor is missing due to data issue.
return null;
}
return product;
}
}
As soon as an exception happens on a JDBC connection, the transaction is considered rollback only, so you can't query the database anymore. You will have to create a new transaction. Overall, it would be better if you join fetch the distributor along when fetching products to avoid this issue. You could achieve that by annotating the findById
method with @EntityGraph("distributors")
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.