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 be abstract, 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)

--

--

--

Java Developer and enthusiast

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

IDFA vs. IDFV — Identifiers for Advertising and Tracking on iOS

Python — Data Types and Variables

How to Setup Redis Replication

How to Setup Redis Replication

Remote Method Invocation

Ghost & Gatsby  —  A perfect blogging platform

Serverless TradingBot

Autonomy’s building at Solana Ignition Hackathon

Visualize Combine Magic with SwiftUI Part 1

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
PA

PA

Java Developer and enthusiast

More from Medium

Controller Annotation in Spring boot

JPA Key Notes

Returning non entity object like DTO in Spring Data JPA Repository method

Spring Boot secrets encryption using Jasypt

Spring boot with Jasypt for secrets encryption and decryption