I have two cases where child entity save works differently when invoked from different context.
When I update child with no cascading parent, modified data is also updated, but this happens only from controller, if I invoke from CommandLineRunner that parent update doesn't happen.
This is my service
@Service
public class BookService {
private final BookAuthorRepository bookAuthorRepository;
private final BookRepository bookRepository;
@Autowired
public BookService(BookAuthorRepository bookAuthorRepository, BookRepository bookRepository) {
this.bookAuthorRepository = bookAuthorRepository;
this.bookRepository = bookRepository;
}
public void updateBookAuth() {
Book book = bookRepository.findById(3).get();
book.setName("should not update");
book.getBookAuthor().setName("new name");
bookAuthorRepository.save(book.getBookAuthor());
}
}
When I invoke this from class below, only BookAuthor name is updated, which is the right behaviour.
@Component
public class MyRunner implements CommandLineRunner {
@Autowired
private BookService bookService;
@Override
public void run(String... args) throws Exception {
bookService.updateBookAuth();
}
}
But if I invoke this service method from controller :
@RestController
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
@GetMapping("/")
public void test() {
bookService.updateBookAuth();
}
}
then both Book name and BookAuthor name are updated, but I didn't understand why Book name is updated.
Here are the entities :
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@OneToOne
private BookAuthor bookAuthor;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public BookAuthor getBookAuthor() {
return bookAuthor;
}
public void setBookAuthor(BookAuthor bookAuthor) {
this.bookAuthor = bookAuthor;
}
}
@Entity
public class BookAuthor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@OneToOne(mappedBy = "bookAuthor")
private Book book;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
}
I thought about transactional also, if I write transaction on method then all context is opened and both parent-child will be updated but in this case I don't use it so why is it happening ?