1 Aralık 2022 Perşembe

MetadataBuilderContributor Arayüzü - Custom SQL Metodu İçindir

Giriş
Açıklaması şöyle
Since Hibernate 5.2.18, you can use the MetadataBuilderContributor utility to customize the MetadataBuilder even if you are bootstrapping via JPA.
Örnek
Şöyle yaparız
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.spi.MetadataBuilderContributor; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.type.BooleanType; public class SQLFunctionContributor implements MetadataBuilderContributor { @Override public void contribute(MetadataBuilder metadataBuilder) { metadataBuilder.applySqlFunction("json_contains_key", new SQLFunctionTemplate(BooleanType.INSTANCE, "JSON_CONTAINS(?1, JSON_QUOTE(?2))")); } }
Açıklaması şöyle
In the above snippet, I am overriding the contribute method by providing one of the MySQL JSON functions.

The JSON_CONTAINS() function checks whether one JSON document contains another JSON document.

JSON_CONTAINS(target_json, candidate_json)

Parameters

target_jsonRequired. A JSON document.

candidate_jsonRequired. The included JSON document.

As you see, I have created a custom key “json_contains_key”. This actually will be used in Criteria API or Query DSL and will be parsed by Hibernate as JSON_CONTAINS().

And provide the custom MetadataBuilderContributor to Hibernate via the hibernate.metadata_builder_contributor configuration property.

spring.jpa.properties.hibernate.metadata_builder_contributor=com.abhicodes.customdialect.util.SQLFunctionContributor



8 Kasım 2022 Salı

PostDeleteEventListener Arayüzü

Giriş
Şu satırı dahil ederiz
import org.hibernate.event.spi.PostDeleteEventListener;
Örnek
Şöyle yaparız
public class HibernateCDCEventListener implements PostDeleteEventListener,
PostUpdateEventListener, PostInsertEventListener { public HibernateCDCEventListener(EntityManagerFactory entityManagerFactory) { SessionFactoryImplementor sessionFactory = entityManagerFactory .unwrap(SessionFactoryImplementor.class); EventListenerRegistry eventListenerRegistry = sessionFactory.getServiceRegistry() .getService(EventListenerRegistry.class); eventListenerRegistry.appendListeners(POST_DELETE, this); eventListenerRegistry.appendListeners(POST_UPDATE, this); eventListenerRegistry.appendListeners(POST_INSERT, this); } @Override public void onPostDelete(final PostDeleteEvent event) { // Handle delete events } @Override public void onPostInsert(final PostInsertEvent event) { processEntity(event.getEntity(), event.getEntity(), event.getEntity()); } @Override public void onPostUpdate(final PostUpdateEvent event) { processEntity(event.getEntity(), event.getEntity(), event.getEntity()); } @Override public boolean requiresPostCommitHanding(final EntityPersister persister) { return false; } }

7 Haziran 2022 Salı

HibernateSearch @NaturalId Anotasyonu

Giriş
Şu satırı dahil ederiz.
import org.hibernate.annotations.NaturalId;
Örnek
Şöyle yaparız
@Indexed
@Entity
@Table
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class Plant {
  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @FullTextField()
  @NaturalId
  private String name;

  @FullTextField
  @NaturalId
  private String scientificName;

  @FullTextField
  private String family;

  private Instant createdAt ;
}


18 Nisan 2022 Pazartesi

HibernateSearch @FullTextFieldAnotasyonu

Giriş
Şu satırı dahil ederiz.
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
Açıklaması şöyle
we annotate the fields we want to search on with the @FullTextField annotation. This annotation works only for string fields, but others exist for fields of different types.
Örnek
Şöyle yaparız
import org.hibernate.annotations.NaturalId;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;


@Indexed
@Entity
@Table(name = "plant")
public class Plant {

  @FullTextField
  @NaturalId
  private String name;

  @FullTextField
  @NaturalId
  private String scientificName;

  @FullTextField
  private String family;
  
}



7 Kasım 2021 Pazar

@Length Anotasyonu - Bean Validation

Giriş
Şu satırı dahil ederiz. Bean validation için kullanılır
import org.hibernate.validator.constraints.Length;
Örnek
Şöyle yaparız
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;

public record EnterpriseRecord(String id, 
  @NotNull String name, 
  @NotNull @Length(min = 2, max = 255) String address) {
}

12 Ekim 2021 Salı

StatelessSession Arayüzü - Batch İşler İçin Uygundur

Giriş
Hibernate Session arayüzü gibidir. Cache kullanmaz. Batch işler için uygundur.

beginTransaction metodu
Şöyle yaparız.
Foo foo = ...;

StatelessSession statelessSession = ...;
Transaction transaction = statelessSession.beginTransaction();

statelessSession.insert(foo);


transaction.commit(); 
getNamedQuery metodu
Örnek
Şöyle yaparız
StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
   
ScrollableResults articles = session.getNamedQuery("GetArticles")
    .scroll(ScrollMode.FORWARD_ONLY);
while ( articles.next() ) {
    Article article = (Article) articles(0);
    article.updateName(newArticleName);
    session.update(article);
}
   
tx.commit();
session.close();


28 Eylül 2021 Salı

HibernateSearch MassIndexer Arayüzü

Giriş
Şu satırı dahil ederiz
import org.hibernate.search.MassIndexer;
massIndexer metodu - Class
Hangi sınıfların indeksleneceğini belirtmek için kullanılır

Örnek
Şöyle yaparız
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.massindexing.MassIndexer;
import org.hibernate.search.mapper.orm.session.SearchSession;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;

@Transactional
@Component
public class Indexer {

  private EntityManager entityManager;

  private static final int THREAD_NUMBER = 4;

  public Indexer(EntityManager entityManager) {
    this.entityManager = entityManager;
  }

  public void indexPersistedData(String indexClassName) throws IndexException {

    try {
      SearchSession searchSession = Search.session(entityManager);

      Class<?> classToIndex = Class.forName(indexClassName);
      MassIndexer indexer = searchSession
        .massIndexer(classToIndex)
        .threadsToLoadObjects(THREAD_NUMBER);

        indexer.startAndWait();
    } catch (Exception e) {
      ...
  }
}
Şöyle yaparız
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ApplicationRunner buildIndex(Indexer indexer) throws Exception {
        return (ApplicationArguments args) -> {
            indexer.indexPersistedData("com.mozen.springboothibernatesearch.model.Plant");
        };
    }
}
startAndWait metodu
Burada massIndexer() metoduna sınıf ismi geçilmiyor.

Örnek
Şöyle yaparız
@Configuration
public class HibernateSearchIndexBuild implements ApplicationListener<ApplicationReadyEvent>{

  @Autowired
  private EntityManager entityManager;

  @Override
  @Transactional
  public void onApplicationEvent(ApplicationReadyEvent event) {
    SearchSession searchSession = Search.session(entityManager);
    MassIndexer indexer = searchSession.massIndexer()
.idFetchSize(150)
.batchSizeToLoadObjects(25).threadsToLoadObjects(12);
    try {
      indexer.startAndWait();
    } catch (InterruptedException e) {
      ...
    }
  }
}