Defining Entity Listener Class Via @EntityListeners
This application is a sample of using the JPA @MappedSuperclass
and @EntityListeners
with JPA callbacks.
Key points:
- the base class ,
Book
, is not an entity, it can beabstract
, and is annotated with@MappedSuperclass
and@EntityListeners(BookListener.class)
BookListener
defines JPA callbacks (e.g.,@PrePersist
)- subclasses of the base class are mapped in tables that contains columns for the inherited attributes and for their own attibutes
- when any entity that is a subclass of
Book
is persisted, loaded, updated, etc the corresponding JPA callbacks are called
Author.java
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Entity
public class Author implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String genre;
private int age;
}
Book.java
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@MappedSuperclass
@EntityListeners(BookListener.class)
public abstract class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String isbn;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
}
EBook.java
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Ebook extends Book implements Serializable {
private static final long serialVersionUID = 1L;
private String format;
}
Paperback.java
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Paperback extends Book implements Serializable {
private static final long serialVersionUID = 1L;
private String sizeIn;
private String weightLbs;
}
BookListener.java
public class BookListener {
@PrePersist
void onPrePersist(Book book) {
System.out.println("BookListener.onPrePersist(): " + book);
}
@PostPersist
void onPostPersist(Book book) {
System.out.println("BookListener.onPostPersist(): " + book);
}
@PostLoad
void onPostLoad(Book book) {
System.out.println("BookListener.onPostLoad(): " + book);
}
@PreUpdate
void onPreUpdate(Book book) {
System.out.println("BookListener.onPreUpdate(): " + book);
}
@PostUpdate
void onPostUpdate(Book book) {
System.out.println("BookListener.onPostUpdate(): " + book);
}
@PreRemove
void onPreRemove(Book book) {
System.out.println("BookListener.onPreRemove(): " + book);
}
@PostRemove
void onPostRemove(Book book) {
System.out.println("BookListener.onPostRemove(): " + book);
}
}
AuthorRepository.java
@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {
@Transactional(readOnly=true)
Author findByName(String name);
}
EbookRepository.java
@Repository
public interface EbookRepository extends JpaRepository<Ebook, Long>{
@Transactional(readOnly = true)
Ebook findByTitle(String title);
@Transactional(readOnly = true)
@Query("SELECT e FROM Ebook e JOIN FETCH e.author")
Ebook fetchByAuthorId(Long id);
}
PaperbackRepository.java
@Repository
public interface PaperbackRepository extends JpaRepository<Paperback, Long> {
@Transactional(readOnly = true)
Paperback findByTitle(String title);
@Transactional(readOnly = true)
@Query("SELECT e FROM Paperback e JOIN FETCH e.author")
Paperback fetchByAuthorId(Long id);
}
BookstoreService.java
@Service
public class BookstoreService {
@Autowired
private AuthorRepository authorRepository;
@Autowired
private PaperbackRepository paperbackRepository;
@Autowired
private EbookRepository ebookRepository;
@Transactional
public void persistAuthorWithBooks() {
Author author = new Author();
author.setName("Alicia Tom");
author.setAge(38);
author.setGenre("Anthology");
Paperback paperback = new Paperback();
paperback.setIsbn("002-AT");
paperback.setTitle("The beatles anthology");
paperback.setSizeIn("7.5 x 1.3 x 9.2");
paperback.setWeightLbs("2.7");
paperback.setAuthor(author);
Ebook ebook = new Ebook();
ebook.setIsbn("003-AT");
ebook.setTitle("Anthology myths");
ebook.setFormat("kindle");
ebook.setAuthor(author);
authorRepository.save(author);
paperbackRepository.save(paperback);
ebookRepository.save(ebook);
}
@Transactional
public void fetchAndRemovePaperback() {
Paperback paperback = paperbackRepository.findByTitle("The beatles anthology");
paperbackRepository.delete(paperback);
}
@Transactional
public void fetchAndRemoveEbook() {
Ebook ebook = ebookRepository.findByTitle("Anthology myths");
ebookRepository.delete(ebook);
}
}
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/bookstoredb?createDatabaseIfNotExist=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.open-in-view=false
#logging.level.org.hibernate.type.descriptor.sql=TRACE
MainApp.java
@SpringBootApplication
public class MainApplication {
@Autowired
private BookstoreService bookstoreService;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@Bean
public ApplicationRunner init() {
return args -> {
System.out.println("\n\npersistAuthorWithBooks():");
bookstoreService.persistAuthorWithBooks();
System.out.println("\n\nfetchAndRemovePaperback():");
bookstoreService.fetchAndRemovePaperback();
System.out.println("\n\nfetchAndRemoveEbook():");
bookstoreService.fetchAndRemoveEbook();
};
}
}
Console.output
persistAuthorWithBooks():
Hibernate: insert into author (age, genre, name) values (?, ?, ?)
BookListener.onPrePersist(): Paperback(sizeIn=7.5 x 1.3 x 9.2, weightLbs=2.7)
Hibernate: insert into paperback (author_id, isbn, title, size_in, weight_lbs) values (?, ?, ?, ?, ?)
BookListener.onPostPersist(): Paperback(sizeIn=7.5 x 1.3 x 9.2, weightLbs=2.7)
BookListener.onPrePersist(): Ebook(format=kindle)
Hibernate: insert into ebook (author_id, isbn, title, format) values (?, ?, ?, ?)
BookListener.onPostPersist(): Ebook(format=kindle)
fetchAndRemovePaperback():
Hibernate: select paperback0_.id as id1_2_, paperback0_.author_id as author_i6_2_, paperback0_.isbn as isbn2_2_, paperback0_.title as title3_2_, paperback0_.size_in as size_in4_2_, paperback0_.weight_lbs as weight_l5_2_ from paperback paperback0_ where paperback0_.title=?
BookListener.onPostLoad(): Paperback(sizeIn=7.5 x 1.3 x 9.2, weightLbs=2.7)
BookListener.onPreRemove(): Paperback(sizeIn=7.5 x 1.3 x 9.2, weightLbs=2.7)
Hibernate: delete from paperback where id=?
BookListener.onPostRemove(): Paperback(sizeIn=7.5 x 1.3 x 9.2, weightLbs=2.7)
fetchAndRemoveEbook():
Hibernate: select ebook0_.id as id1_1_, ebook0_.author_id as author_i5_1_, ebook0_.isbn as isbn2_1_, ebook0_.title as title3_1_, ebook0_.format as format4_1_ from ebook ebook0_ where ebook0_.title=?
BookListener.onPostLoad(): Ebook(format=kindle)
BookListener.onPreRemove(): Ebook(format=kindle)
Hibernate: delete from ebook where id=?
BookListener.onPostRemove(): Ebook(format=kindle)