简体   繁体   中英

hibernate could not initialize lazy entity after exception in same session

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:

  1. Is my understanding correct?
  2. How to make hibernate discard all the entites it initialized previously if an exception occurred. Or how to solve this issue.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM