Reputation: 45
I have a problem that after trying many formulas and ... I ran out of ideas and would like to see if anyone can help me in this.
I am trying to insert a parent and child table with JPA but not adding the id of the parent table to the daughter. Insert the record in the daughter too but the id leaves me null. These would be the two tables.
The Author table only has two columns and a 1 / N relationship with the Book daughter table indicating a HashSet: La tabla Autor, solo tiene dos columnas y una relación 1/N con la tabla hija Libro indicando un HashSet:
@Entity
@Table(name="author")
public class Author {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id", nullable = false, insertable=false)
private int id;
@Column(name="name", columnDefinition = "varchar(127)")
private String name;
@Column(name="description", columnDefinition = "varchar(255)")
private String description;
@OneToMany(mappedBy = "author", cascade=CascadeType.ALL, orphanRemoval = true)
private Set<Book> book = new HashSet<Book>();
/* Getters y Setters y Constructor */
}
The Book table, I tell you to add a column that will be the foreign key of Author and that will be called autor_id. It is this field that is not automatically filled with the parent id:
@Entity
@Table(name="book")
public class Book {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id", nullable = false, insertable=false)
private int id;
@Column(name="title", columnDefinition = "varchar(50)")
private String title;
@Column(name="description", columnDefinition = "varchar(255)")
private String description;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(foreignKey = @ForeignKey(name = "fk_book_author_id"), name="author_id", referencedColumnName = "id", columnDefinition = "int")
private Author author;
/* Getters y Setters y Constructor */
}
The Controller, I simply have a GetMapping to load the list per screen and the Post where I create the author and the book and add the latter to the author to later make a save in the Repository call:
@Controller
@RequestMapping("/authors")
public class Authors {
@Autowired
private AuthorRepository authorRepository;
@GetMapping
public String findAll(Model model) {
extracted(model);
return "authors";
}
@PostMapping
public String save(Model model) {
Author author = new Author();
author.setName("Name");
author.setDescription("Description Author");
Book book = new Book();
book.setTitle("Title");
book.setDescription("Description Book");
Set<Book> hsBook = new HashSet<Book>();
hsBook.add(book);
author.setBook(hsBook);
authorRepository.save(author);
extracted(model);
return "authors";
}
private void extracted(Model model) {
model.addAttribute("authors", authorRepository.findAll());
}
}
The little Repository to add here except for the extends JpaRepository:
@Repository
public interface AuthorRepository extends JpaRepository<Author, Integer> {
}
This saves me in the Author table:
id = 1, name = "Name", description = "Description Author"
And in the Book table:
id = 1, author_id = null, title = "Title", description = "Description Book"
I have tried in several ways but I cannot transfer the id of the Author table to the foreign key.
What am I doing wrong?
Thank you very much for your time.
Upvotes: 1
Views: 3972
Reputation: 753
You forgot to assign reference of author
to book
as mentioned by @Eklavya.
It is best practise to introduce add
and remove
utility methods to avoid this state propagation issue.
@Entity
@Table(name = "author")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, insertable = false)
private int id;
@Column(name = "name", columnDefinition = "varchar(127)")
private String name;
@Column(name = "description", columnDefinition = "varchar(255)")
private String description;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Object> books = new HashSet<Book>();
/* Getters y Setters y Constructor */
public void addBook(Book book) {
books.add(book);
book.setAuthor(this);
}
public void removeBook(Book book) {
books.add(book);
book.setAuthor(null);
}
}
Then your save
method becomes
@PostMapping
public String save(Model model) {
Author author = new Author();
author.setName("Name");
author.setDescription("Description Author");
Book book = new Book();
book.setTitle("Title");
book.setDescription("Description Book");
author.addBook(book);
authorRepository.save(author);
extracted(model);
return "authors";
}
I hope this is helpful.
Upvotes: 0
Reputation: 18420
You need to sync both parent and child for bidirectional relationships.
Set author
in book
object also before save the author
book.setAuthor(author);
Upvotes: 2