Reputation: 2544
I'm using Hibernate with PostgreSQL
and Hibernate Search (5.7.0.Alpha1
)
with ElasticSearch (2.4.2
).
I have two classes: Book
and Author
.
A book can have many authors
and an author can author more than one book.
I annotated Book
class like this:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
@Indexed
@Entity
public class Book implements Record {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
protected Long id;
@Field
protected String title;
@ManyToMany
@JoinTable(name = "books_authors",
joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "author_id", referencedColumnName = "id"))
@IndexedEmbedded(includeEmbeddedObjectId = true)
protected List<Author> authors = new ArrayList<>();
//constructors, getters and setters
//...
}
The problem is that when an author gets updated (for example their name changes), the document of the correspoding book does not change in ElasticSearch.
For example after executing this code:
package com.example.app;
import com.example.app.model.Author;
import com.example.app.model.Book;
import com.example.app.model.Category;
import java.io.IOException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class App
{
public static void main(String[] args) throws IOException
{
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Author author01 = new Author("Author 01");
Book book01 = new Book("Book 01");
book01.addAuthor(author01);
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(author01);
session.save(book01);
session.getTransaction().commit();
session.close();
}
author01.setName("Author 02");
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.saveOrUpdate(author01);
session.getTransaction().commit();
session.close();
}
//without this the app won't end
System.exit(0);
}
}
the author document in ElasticSearch will get updated, but the book document will not change:
{"_index":"com.example.app.model.author","_type":"com.example.app.model.Author","_id":"2","_score":1,
"_source":{"name":"Author 02"}}
{"_index":"com.example.app.model.book","_type":"com.example.app.model.Book","_id":"3","_score":1,
"_source":{"title":"Elementy","authors":[{"name":"Author 01", "id":"2"}]}}}
I read that for the situations like this I need to use @ContainedIn
annotation at the Author
side,
so I did. For this reason I needed to add the property authoredBooks
, I didn't plan it before.
package com.example.app.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
@Indexed
@Entity
public class Author {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
protected long id;
@Field
protected String name;
@ContainedIn
@ManyToMany(mappedBy = "authors")
private List<Book> authoredBooks = new ArrayList<>();
//constructors, getters and setters
//...
}
This however did not change the behaviour of Hibernate Search, so book document is still not updated. Could you give some hints on what can I do or check?
Upvotes: 2
Views: 1428
Reputation: 9977
I'm using Hibernate with PostgreSQL and Hibernate Search (5.7.0.Alpha1) with ElasticSearch (2.4.2).
First thing to do would be to upgrade to an actual release of Hibernate Search (not an Alpha or Beta), to be sure you're not experiencing a bug that has been solved since.
Apart from that... your initial code only updates one side of the relationship; did you make sure to add a author01.addBook(book01)
line after ook01.addAuthor(author01)
?
Upvotes: 1