I have two tables in my db Brand
and Product
with the next simple structure:
| Brand | id PK |
| Product | id PK | brand_id FK |
and entities for that tables:
@Entity
@Table(name = "Brand")
public class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "brand")
private String brand;
/* getters and setters */
}
@Entity
@Table(name = "Product")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "brand_id")
private Brand brand;
/* getters and setters */
}
As I use Spring-Data I have repository and service with implementation for Brand:
@Repository
public interface BrandRepository extends JpaRepository<Brand, Long> {
Brand findByBrand(String brand);
}
public interface BrandService {
Brand findByBrand(String brand);
}
@Service
public class BrandServiceImpl implements BrandService {
@Autowired
private BrandRepository brandRepository;
@Override
public Brand findByBrand(String brand) {
return brandRepository.findByBrand(brand);
}
}
and for Product:
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
public interface ProductService {
Product save(Product product);
}
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductRepository productRepository;
@Override
public Product save(Product product) {
return productRepository.save(product);
}
}
The goal is to save Product object. Brand object should be saved automatically if it doesn't exist in db or should be set to Product otherwise:
Brand brand = brandService.findByBrand(brandName);
if (brand == null) {
brand = new Brand();
brand.setBrand("Some name");
}
product.setBrand(brand);
productService.save(product);
It works fine if Brand object with specified brandName is not in my db. But if it is I get:
PersistentObjectException: detached entity passed to persist
for Brand.
I can change cascade type to MERGE and it will work fine. But if I run the code with MERGE cascade type and Brand object with specified brandName is not in my db I get
IllegalStateException:
org.hibernate.TransientPropertyValueException:
object references an unsaved transient instance - save the transient instance before flushing
for Brand (that's really not surprised).
What Cascade Type should be? Ot what I did wrong?