Created
March 21, 2021 16:07
-
-
Save silentsudo/328d937e5fbfd09d19c3dc6463b0a40a to your computer and use it in GitHub Desktop.
hibernate-entity-event-listener
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.samplejdbctemplatecall; | |
import lombok.AllArgsConstructor; | |
import lombok.Getter; | |
import lombok.NoArgsConstructor; | |
import lombok.Setter; | |
import lombok.extern.slf4j.Slf4j; | |
import org.hibernate.boot.Metadata; | |
import org.hibernate.engine.spi.SessionFactoryImplementor; | |
import org.hibernate.event.service.spi.EventListenerGroup; | |
import org.hibernate.event.service.spi.EventListenerRegistry; | |
import org.hibernate.event.spi.EventType; | |
import org.hibernate.event.spi.PostInsertEvent; | |
import org.hibernate.event.spi.PostInsertEventListener; | |
import org.hibernate.integrator.spi.Integrator; | |
import org.hibernate.jpa.boot.spi.IntegratorProvider; | |
import org.hibernate.persister.entity.EntityPersister; | |
import org.hibernate.service.spi.SessionFactoryServiceRegistry; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.data.repository.CrudRepository; | |
import org.springframework.stereotype.Component; | |
import org.springframework.stereotype.Repository; | |
import org.springframework.stereotype.Service; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RestController; | |
import javax.persistence.Entity; | |
import javax.persistence.GeneratedValue; | |
import javax.persistence.GenerationType; | |
import javax.persistence.Id; | |
import java.util.Collections; | |
import java.util.Map; | |
import java.util.UUID; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ConcurrentMap; | |
@RequestMapping(path = "/entity-listener") | |
@RestController | |
public class SampleLogController { | |
private final SampleLogRepository sampleLogRepository; | |
private final SampleLogEntries sampleLogEntiries; | |
@Autowired | |
public SampleLogController(SampleLogRepository sampleLogRepository, SampleLogEntries sampleLogEntiries) { | |
this.sampleLogRepository = sampleLogRepository; | |
this.sampleLogEntiries = sampleLogEntiries; | |
} | |
// This is usually post method but for test purpose creating new log with uuid random and inserting | |
@GetMapping(path = "insert") | |
public SampleLog insertNewEntry() { | |
final String uuid = UUID.randomUUID().toString(); | |
final SampleLog sampleLog = new SampleLog(); | |
sampleLog.setMessage(uuid); | |
return sampleLogRepository.save(sampleLog); | |
} | |
@GetMapping(path = "list-recent-inserts") | |
public Map<Long, String> entries() { | |
return sampleLogEntiries.data(); | |
} | |
} | |
@Slf4j | |
@Component | |
class HibernateConfig implements HibernatePropertiesCustomizer { | |
private final JpaEventListenerIntegrator jpaEventListenerIntegrator; | |
@Autowired | |
HibernateConfig(JpaEventListenerIntegrator jpaEventListenerIntegrator) { | |
this.jpaEventListenerIntegrator = jpaEventListenerIntegrator; | |
} | |
@Override | |
public void customize(Map<String, Object> hibernateProperties) { | |
log.warn("Called hibernate configuration"); | |
hibernateProperties.put("hibernate.integrator_provider", | |
(IntegratorProvider) () -> Collections.singletonList(jpaEventListenerIntegrator)); | |
} | |
} | |
@Configuration | |
class SampleConfiguration { | |
@Bean | |
SampleLogEntries sampleEntries() { | |
return new SampleLogEntries(); | |
} | |
} | |
class SampleLogEntries { | |
private final ConcurrentMap<Long, String> map = new ConcurrentHashMap<>(); | |
public void add(SampleLog sampleLog) { | |
this.map.put(sampleLog.getId(), sampleLog.getMessage()); | |
} | |
public Map<Long, String> data() { | |
return Collections.unmodifiableMap(this.map); | |
} | |
} | |
@Repository | |
interface SampleLogRepository extends CrudRepository<SampleLog, Long> { | |
} | |
@Getter | |
@Setter | |
@NoArgsConstructor | |
@AllArgsConstructor | |
@Entity | |
class SampleLog { | |
@Id | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | |
private Long id; | |
private String message; | |
} | |
@Service | |
@Slf4j | |
class JpaEventListenerIntegrator implements Integrator, PostInsertEventListener { | |
private final SampleLogEntries sampleLogEntiries; | |
@Autowired | |
JpaEventListenerIntegrator(SampleLogEntries sampleLogEntiries) { | |
this.sampleLogEntiries = sampleLogEntiries; | |
} | |
@Override | |
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { | |
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); | |
eventListenerRegistry | |
.appendListeners(EventType.POST_INSERT, this); | |
} | |
@Override | |
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { | |
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); | |
EventListenerGroup<PostInsertEventListener> eventListenerGroup = eventListenerRegistry | |
.getEventListenerGroup(EventType.POST_INSERT); | |
log.info("listener attached were: " + eventListenerGroup.getClass().getSimpleName()); | |
log.error("disintegrate : " + getClass().getCanonicalName()); | |
eventListenerGroup.clearListeners(); | |
} | |
@Override | |
public void onPostInsert(PostInsertEvent event) { | |
log.info("Inserted : " + event.getEntity()); | |
final Object entity = event.getEntity(); | |
if (entity instanceof SampleLog) { | |
sampleLogEntiries.add((SampleLog) entity); | |
} | |
} | |
@Override | |
public boolean requiresPostCommitHanding(EntityPersister persister) { | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment