All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vladmihalcea.spring.repository.HibernateRepositoryImpl Maven / Gradle / Ivy

There is a newer version: 2.21.1
Show newest version
package com.vladmihalcea.spring.repository;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.hibernate.Session;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.AbstractSharedSessionContract;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

/**
 * @author Vlad Mihalcea
 */
public class HibernateRepositoryImpl implements HibernateRepository {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public  S save(S entity) {
        return unsupported();
    }

    @Override
    public  List saveAll(Iterable entities) {
        return unsupported();
    }

    @Override
    public  S saveAndFlush(S entity) {
        return unsupported();
    }

    @Override
    public  List saveAllAndFlush(Iterable entities) {
        return unsupported();
    }

    public  S persist(S entity) {
        entityManager.persist(entity);
        return entity;
    }

    public  S persistAndFlush(S entity) {
        persist(entity);
        entityManager.flush();
        return entity;
    }

    public  List persistAll(Iterable entities) {
        List result = new ArrayList<>();
        for(S entity : entities) {
            result.add(persist(entity));
        }
        return result;
    }

    public  List peristAllAndFlush(Iterable entities) {
        return executeBatch(() -> {
            List result = new ArrayList<>();
            for(S entity : entities) {
                result.add(persist(entity));
            }
            entityManager.flush();
            return result;
        });
    }

    public  S merge(S entity) {
        return entityManager.merge(entity);
    }

    @Override
    public  S mergeAndFlush(S entity) {
        S result = merge(entity);
        entityManager.flush();
        return result;
    }

    @Override
    public  List mergeAll(Iterable entities) {
        List result = new ArrayList<>();
        for(S entity : entities) {
            result.add(merge(entity));
        }
        return result;
    }

    @Override
    public  List mergeAllAndFlush(Iterable entities) {
        return executeBatch(() -> {
            List result = new ArrayList<>();
            for(S entity : entities) {
                result.add(merge(entity));
            }
            entityManager.flush();
            return result;
        });
    }

    public  S update(S entity) {
        session().update(entity);
        return entity;
    }

    @Override
    public  S updateAndFlush(S entity) {
        update(entity);
        entityManager.flush();
        return entity;
    }

    @Override
    public  List updateAll(Iterable entities) {
        List result = new ArrayList<>();
        for(S entity : entities) {
            result.add(update(entity));
        }
        return result;
    }

    @Override
    public  List updateAllAndFlush(Iterable entities) {
        return executeBatch(() -> {
            List result = new ArrayList<>();
            for(S entity : entities) {
                result.add(update(entity));
            }
            entityManager.flush();
            return result;
        });
    }

    protected Integer getBatchSize(Session session) {
        SessionFactoryImplementor sessionFactory = session.getSessionFactory().unwrap(SessionFactoryImplementor.class);
        final JdbcServices jdbcServices = sessionFactory.getServiceRegistry().getService(JdbcServices.class);
        if(!jdbcServices.getExtractedMetaDataSupport().supportsBatchUpdates()) {
            return Integer.MIN_VALUE;
        }
        return session.unwrap(AbstractSharedSessionContract.class).getConfiguredJdbcBatchSize();
    }

    protected  R executeBatch(Supplier callback) {
        Session session = session();
        Integer jdbcBatchSize = getBatchSize(session);
        Integer originalSessionBatchSize = session.getJdbcBatchSize();
        try {
            if (jdbcBatchSize == null) {
                session.setJdbcBatchSize(10);
            }
            return callback.get();
        } finally {
            session.setJdbcBatchSize(originalSessionBatchSize);
        }
    }

    protected Session session() {
        return entityManager.unwrap(Session.class);
    }

    protected  S unsupported() {
        throw new UnsupportedOperationException("There's no such thing as a save method in JPA, so don't use this hack!");
    }
}