Issue
I'm writing a program in which an object holds a bidirectional relationship with another product. I'm using the Jpa module with Spring Boot to do so. My object "Bon" holds a set of "Products". Inside my program, the service seems to do everything right when System.out.printing values to check. Though eventually, the id's of the product do not get saved in the database, it remains a null value.
Object consignatiebon (I only showed relevant methods etc.):
@Entity
@Table(name = "consignatieBonnen")
public class Consignatiebon {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private long idConsignatiebon;
... methods ...
@OneToMany(mappedBy = "consignatiebon")
private Set<Product> productSet = new LinkedHashSet<>();
public Consignatiebon(ObjectA objecta, ObjectB objectb, ..) {
this.objecta = objecta;
this.objectb = objectb;
this.productSet = new LinkedHashSet<>();
}
//relevant methods
public Set<Product> getProductSet() {
return Collections.unmodifiableSet(productSet);
}
public boolean add(Product product) {
if(product == null) {
throw new NullPointerException();
}
return productSet.add(product);
}
//overridden equals & hashtagcode, but I do not think it is relevant to show.
}
corresponding ProductObject (took only relevant things again):
@Entity
@Table(name = "producten")
public class Product {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private long productId;
@ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "consignatiebonId")
private Consignatiebon consignatiebon;
public Consignatiebon(Consignatiebon consignatiebon, ObjectB objectb, ..) {
this.consignatiebon = consignatiebon;
this.objectb = objectb;
}
//normal getters and setters
//overridden equals & hashtagcode, but I do not think it is relevant to show.
}
I use twice simple JpaRepositories:
public interface ProductRepository extends JpaRepository <Product,Long> {
}
public interface ConsignatiebonRepository extends JpaRepository<Consignatiebon, Long> {
}
Here you can find my service where the action happens:
@Service
@Transactional
public class DefaultProductService implements ProductService {
private final ProductRepository productRepository;
private final ConsignatiebonRepository consignatiebonRepository;
public DefaultProductService(ProductRepository productRepository, ConsignatiebonRepository consignatiebonRepository) {
this.productRepository = productRepository;
this.consignatiebonRepository = consignatiebonRepository;
}
@Override
public List<Product> findAllProducts() {
return productRepository.findAll();
}
@Override
public void genereerBarcode(long id) {
try {
productRepository.findById(id)
.orElseThrow(ProductNietGevondenException::new)
.generateAndSetEAN13BarcodeImage();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@Transactional
public void addBonAndProducts(Boninfo boninfo) {
Consignatiebon bon = new Consignatiebon(necesary things from boninfo);
consignatiebonRepository.save(bon);
consignatiebonRepository.flush();
for(var product:boninfo.getProductlist()) {
product.setConsignatiebon(bon);
productRepository.save(product);
productRepository.flush();
bon.add(product);
}
consignatiebonRepository.save(bon);
}
}
When I system.out.print things inside these code, everything contains whatever it should have. But nevertheless the column which should hold the productid's remains empty. How am I declaring my entities wrong? I really did my best to formulate everything clear and the narrow the problem down. if I'm being unclear, please let me know so I can better the question.
I also add a screenshot here of my full MySQL table.
Solution
But nevertheless the column which should hold the productid's remains empty.
Which column are you talking about? Your model shows a productSet INT
column which Hibernate won't consider. The mapping explicitly says that the data in the set should be determined through the many-to-one association consignatiebon
, so only the producten#consignatiebonId
column will be set by Hibernate.
Answered By - Christian Beikov
Answer Checked By - Robin (JavaFixing Admin)