I'm using Spring Boot in my application. I have a controller which accesses the service layer which accesses my implementation of Spring Data JPA's CrudRepository which interacts with Hibernate to fetch data from the database. All three of the following implementations of CrudRepository return incorrect objects:
public class ProductRepositoryImpl implements ProductRepository {
@Autowired
private SessionFactory sessionFactory;
@SuppressWarnings("unchecked")
public List<Product> findProductBatch(int start, int end) {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("from Product");
query.setFirstResult(start);
query.setMaxResults(end);
List<Product> list = query.list();
return list;
}
@SuppressWarnings({ "unused", "unchecked" })
@Override
public Iterable<Product> findAll() {
Session session = sessionFactory.getCurrentSession();
List<Product> products = session.createQuery("from Product").list();
Iterable<Product> productIterable = products;
return products;
}
@SuppressWarnings("unchecked")
public List<Product> findBatch(int start, int end) {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("from Product");
query.setFirstResult(start);
query.setMaxResults(end);
List<Product> list = query.list();
return list;
}
}
The findOne() method returns a record only if the parameter passed to it is zero, while the record's id is not zero. The following JSON response is returned upon sending a request:
{
"productId": 0,
"name": "xxxxxx",
"productCategoryId": null,
"created": 1482655958000,
"createdBy": null
}
The record exists in the database but its id is 1 and it does have a "productCategoryId" but since it wasn't injected, it returned null.
The findAll() method returns the same record repeated many times and the findBatch() method returns a similar response.
Here's the rest of the code:
Product.java:
@Entity
public class Product {
@Id
private Integer productId;
private String name;
private Integer productCategoryId;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "productCategoryId", insertable = false, updatable = false)
@Autowired
private ProductCategory productCategory;
private Date created;
private Integer createdBy;
public Product() {
}
public Product(Integer productId, String name, ProductCategory productCategory, Integer uomId, Date created, Integer createdBy) {
this.productId = productId;
this.name = name;
this.productCategory = productCategory;
this.created = created;
this.createdBy = createdBy;
}
public Product(String name, ProductCategory productCategory) {
this.name = name;
this.productCategory = productCategory;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(Integer productCategoryId) {
this.productCategoryId = productCategoryId;
}
// public ProductCategory getProductCategory() {
// return productCategory;
// }
//
// public void setProductCategory(ProductCategory productCategory) {
// this.productCategory = productCategory;
// }
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
}
ProductCategory.java:
@Entity
public class ProductCategory {
@Id
private Integer productCategoryId;
private String name;
private Date created;
private Integer createdBy;
public ProductCategory() {
}
public ProductCategory(Integer productCategoryId, String name, Date created, Integer createdBy) {
this.productCategoryId = productCategoryId;
this.name = name;
this.created = created;
this.createdBy = createdBy;
}
public Integer getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(Integer productCategoryId) {
this.productCategoryId = productCategoryId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
}
ProductServiceImpl.java
@Service
@Transactional
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductRepository productRepository;
public Product findOne(int productId) {
return productRepository.findOne(productId);
}
public List<Product> findAll() {
List<Product> products = new ArrayList<>();
productRepository.findAll().forEach(products::add);
return products;
}
@Override
public List<Product> findBatch(int start, int end) {
return productRepository.findBatch(start, end);
}
}
ProductController.java:
@RestController
@RequestMapping("/products")
@EnableTransactionManagement
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping(method = RequestMethod.GET)
public List<Product> findAll() {
List<Product> products = productService.findAll();
return products;
}
@RequestMapping(value = "/{productId}", method = RequestMethod.GET)
public Product findOne(@PathVariable int productId) {
Product product = productService.findOne(productId);
return product;
}
@RequestMapping(value = "/{start}/{end}", method = RequestMethod.GET)
public List<Product> findBatch(@PathVariable int start, @PathVariable int end) {
List<Product> list = productService.findBatch(start, end);
return list;
}
}
ApplicationContextConfig.java:
public class ApplicationContextConfig {
@Bean
public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory emf) {
HibernateJpaSessionFactoryBean factory = new HibernateJpaSessionFactoryBean();
factory.setEntityManagerFactory(emf);
return factory;
}
}
The response should also contain a full injected ProductCategory object which it does not.
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl