From 1b7dffafb82318256d351ec8ba7478b58eaf360b Mon Sep 17 00:00:00 2001 From: mbussolotto Date: Tue, 27 Aug 2024 08:59:16 +0200 Subject: [PATCH] hibernate 6 migration --- .../hibernate/AbstractConnectionManager.java | 13 +- .../common/hibernate/ConnectionManager.java | 22 +-- .../common/hibernate/HibernateFactory.java | 146 ++++++++++-------- .../rhn/domain/errata/CustomEnumType.java | 1 - .../rhn/domain/server/ServerFactory.java | 61 ++++---- .../domain/BillingDimensionEnumType.java | 6 + 6 files changed, 135 insertions(+), 114 deletions(-) diff --git a/java/code/src/com/redhat/rhn/common/hibernate/AbstractConnectionManager.java b/java/code/src/com/redhat/rhn/common/hibernate/AbstractConnectionManager.java index 4a7354becc0a..5f1349a2fe2e 100644 --- a/java/code/src/com/redhat/rhn/common/hibernate/AbstractConnectionManager.java +++ b/java/code/src/com/redhat/rhn/common/hibernate/AbstractConnectionManager.java @@ -26,7 +26,7 @@ import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; -import org.hibernate.metadata.ClassMetadata; +import jakarta.persistence.metamodel.Metamodel; import java.util.ArrayList; import java.util.Arrays; @@ -105,20 +105,13 @@ public boolean isTransactionPending() { return info.getTransaction() != null; } - /** - * {@inheritDoc} - */ @Override - public ClassMetadata getMetadata(Object target) { + public Metamodel getMetadata(Object target) { if (target == null) { return null; } - if (target instanceof Class) { - return sessionFactory.getClassMetadata((Class) target); - } - - return sessionFactory.getClassMetadata(target.getClass()); + return sessionFactory.getMetamodel(); } /** diff --git a/java/code/src/com/redhat/rhn/common/hibernate/ConnectionManager.java b/java/code/src/com/redhat/rhn/common/hibernate/ConnectionManager.java index aba589ed7813..ba9dbf029cb8 100644 --- a/java/code/src/com/redhat/rhn/common/hibernate/ConnectionManager.java +++ b/java/code/src/com/redhat/rhn/common/hibernate/ConnectionManager.java @@ -16,7 +16,8 @@ import org.hibernate.HibernateException; import org.hibernate.Session; -import org.hibernate.metadata.ClassMetadata; + +import jakarta.persistence.metamodel.Metamodel; import java.util.Optional; @@ -54,29 +55,32 @@ public interface ConnectionManager { /** * Check if this connection manager has already been initialized. - - * @return true if {@link #initialize()} has been called and the session factory is available. + * + * @return true if {@link #initialize()} has been called and the session + * factory is available. */ boolean isInitialized(); /** * Allow loading hbm.xml files from additional locations. * - * @param additionalLocation the array of package names to be added to the scan. + * @param additionalLocation the array of package names to be added to the + * scan. */ void setAdditionalPackageNames(String[] additionalLocation); /** * Set the name for Prometheus Hiberante Statistics collector * - * @param componentName The component name for collector registration, used for metric label value + * @param componentName The component name for collector registration, used + * for metric label value */ void setComponentName(String componentName); /** - * Returns Hibernate session stored in ThreadLocal storage. If not - * present, creates a new one and stores it in ThreadLocal; creating the - * session also begins a transaction implicitly. + * Returns Hibernate session stored in ThreadLocal storage. If not present, + * creates a new one and stores it in ThreadLocal; creating the session also + * begins a transaction implicitly. * @return Session asked for */ Session getSession(); @@ -113,7 +117,7 @@ public interface ConnectionManager { * @param target an object instance or a class to retrieve the metadata for * @return the {@link ClassMetadata} for the given object. */ - ClassMetadata getMetadata(Object target); + Metamodel getMetadata(Object target); /** * Closes Hibernate Session stored in ThreadLocal storage. diff --git a/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java b/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java index d809e18c924d..08378fddbb37 100644 --- a/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java +++ b/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java @@ -27,12 +27,14 @@ import org.apache.logging.log4j.Logger; import org.hibernate.Hibernate; import org.hibernate.HibernateException; -import org.hibernate.LockMode; +import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.Session; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metadata.ClassMetadata; import org.hibernate.query.Query; +import org.hibernate.engine.jdbc.LobCreator; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import jakarta.persistence.metamodel.Metamodel; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -67,7 +69,8 @@ */ public abstract class HibernateFactory { - private static ConnectionManager connectionManager = ConnectionManagerFactory.defaultConnectionManager(); + private static ConnectionManager connectionManager = + ConnectionManagerFactory.defaultConnectionManager(); private static final Logger LOG = LogManager.getLogger(HibernateFactory.class); public static final int LIST_BATCH_MAX_SIZE = 1000; @@ -121,7 +124,8 @@ public static void createSessionFactory(String[] additionalLocation) { /** * Register Prometheus Statistics Collector component name - * @param componentName Name of the application component which will be added to the metric as the `unit` label + * @param componentName Name of the application component which will be + * added to the metric as the `unit` label */ public static void registerComponentName(String componentName) { connectionManager.setComponentName(componentName); @@ -149,7 +153,7 @@ private void bindParameters(Query query, Map parameters) return; } - for (Map.Entry entry: parameters.entrySet()) { + for (Map.Entry entry : parameters.entrySet()) { if (entry.getValue() instanceof Collection) { Collection c = (Collection) entry.getValue(); if (c.size() > 1000) { @@ -172,7 +176,8 @@ private void bindParameters(Query query, Map parameters) * map can also be null. * @return Object found by named query or null if nothing found. */ - protected T lookupObjectByNamedQuery(String qryName, Map qryParams) { + protected T lookupObjectByNamedQuery(String qryName, + Map qryParams) { return lookupObjectByNamedQuery(qryName, qryParams, false); } @@ -200,8 +205,9 @@ protected T lookupObjectByNamedQuery(String qryName, Map qry throw new HibernateRuntimeException("Mapping not found for " + qryName, me); } catch (HibernateException he) { - throw new HibernateRuntimeException("Executing query " + qryName + - " with params " + qryParams + " failed", he); + throw new HibernateRuntimeException( + "Executing query " + qryName + " with params " + qryParams + " failed", + he); } } @@ -215,7 +221,8 @@ protected T lookupObjectByNamedQuery(String qryName, Map qry * @return List of objects returned by named query, or null if nothing * found. */ - protected List listObjectsByNamedQuery(String qryName, Map qryParams) { + protected List listObjectsByNamedQuery(String qryName, + Map qryParams) { return listObjectsByNamedQuery(qryName, qryParams, false); } @@ -231,8 +238,8 @@ protected List listObjectsByNamedQuery(String qryName, Map List listObjectsByNamedQuery(String qryName, Map qryParams, - Collection col, String colLabel) { + protected List listObjectsByNamedQuery(String qryName, + Map qryParams, Collection col, String colLabel) { if (col.isEmpty()) { return Collections.emptyList(); @@ -253,8 +260,6 @@ protected List listObjectsByNamedQuery(String qryName, Map List listObjectsByNamedQuery(String qryName, Map List listObjectsByNamedQuery(String qryName, Map qryParams, boolean cacheable) { + protected List listObjectsByNamedQuery(String qryName, + Map qryParams, boolean cacheable) { Session session = HibernateFactory.getSession(); Query query = session.getNamedQuery(qryName); query.setCacheable(cacheable); @@ -317,7 +323,8 @@ protected int removeObject(Object toRemove) { } /** - * Deletes rows corresponding to multiple objects (as in DELETE FROM... IN ...). + * Deletes rows corresponding to multiple objects (as in DELETE FROM... IN + * ...). * * @param objects the objects to delete * @param clazz class of the objects to delete @@ -367,7 +374,8 @@ public static void commitTransaction() throws HibernateException { } /** - * Roll back transaction in case it is not committed and close the Hibernate session. + * Roll back transaction in case it is not committed and close the Hibernate + * session. * * @param committed - if it was possible to commit the transaction. */ @@ -447,10 +455,10 @@ public Object getObject(Class clazz, Serializable id) { } /** - * Return a locked persistent instance of the given entity class with - * the given identifier, or null if there is no such persistent instance. - * (If the instance, or a proxy for the instance, is already associated - * with the session, return that instance or proxy.) + * Return a locked persistent instance of the given entity class with the + * given identifier, or null if there is no such persistent instance. (If + * the instance, or a proxy for the instance, is already associated with the + * session, return that instance or proxy.) * @param clazz a persistent class * @param id an identifier * @return Object persistent instance or null @@ -462,7 +470,7 @@ protected Object lockObject(Class clazz, Serializable id) { try { session = HibernateFactory.getSession(); - retval = session.get(clazz, id, LockMode.UPGRADE); + retval = session.get(clazz, id, LockOptions.UPGRADE); } catch (MappingException me) { getLogger().error("Mapping not found for {}", clazz.getName(), me); @@ -484,17 +492,17 @@ protected Object lockObject(Class clazz, Serializable id) { */ public static T reload(T obj) throws HibernateException { // assertNotNull(obj); - ClassMetadata cmd = connectionManager.getMetadata(obj); - Serializable id = cmd.getIdentifier(obj, (SessionImplementor) getSession()); + Metamodel cmd = connectionManager.getMetadata(obj); + Object id = cmd.getIdentifier(obj, (SessionImplementor) getSession()); Session session = getSession(); session.flush(); session.evict(obj); /* * In hibernate 3, the following doesn't work: - * session.load(obj.getClass(), id); - * load returns the proxy class instead of the persisted class, ie, - * Filter$$EnhancerByCGLIB$$9bcc734d_2 instead of Filter. - * session.get is set to not return the proxy class, so that is what we'll use. + * session.load(obj.getClass(), id); load returns the proxy class + * instead of the persisted class, ie, + * Filter$$EnhancerByCGLIB$$9bcc734d_2 instead of Filter. session.get is + * set to not return the proxy class, so that is what we'll use. */ // assertNotSame(obj, result); return (T) session.get(obj.getClass(), id); @@ -511,7 +519,8 @@ public static byte[] blobToByteArray(Blob fromBlob) { return new byte[0]; } - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = fromBlob.getBinaryStream()) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream is = fromBlob.getBinaryStream()) { IOUtils.copy(is, baos, 4000); return baos.toByteArray(); } @@ -526,8 +535,8 @@ public static byte[] blobToByteArray(Blob fromBlob) { } /** - * Get the String version of the byte array contents - * used to return the string representation of byte arrays constructed from blobs + * Get the String version of the byte array contents used to return the + * string representation of byte arrays constructed from blobs * @param barr byte array to convert to String * @return String version of the byte array contents */ @@ -545,8 +554,8 @@ public static String getByteArrayContents(byte[] barr) { * Get the String version of an object corresponding to a BLOB column * Handles both the byte[] and the Blob cases * @param blob the blob to handle - * @return String version of the blob contents, null if the blob was null - * or if the specified object is not actually a Blob + * @return String version of the blob contents, null if the blob was null or + * if the specified object is not actually a Blob */ public static String getBlobContents(Object blob) { // Returned by Hibernate, and also returned by mode queries @@ -562,10 +571,11 @@ public static String getBlobContents(Object blob) { } /** - * Convert a byte[] array to a Blob object. Guards against - * null arrays and 0 length arrays. + * Convert a byte[] array to a Blob object. Guards against null arrays and 0 + * length arrays. * @param data array to convert to a Blob - * @return Blob if data[] is non-null and {@literal length > 0}, null otherwise + * @return Blob if data[] is non-null and {@literal length > 0}, null + * otherwise */ public static Blob byteArrayToBlob(byte[] data) { if (data == null) { @@ -579,10 +589,11 @@ public static Blob byteArrayToBlob(byte[] data) { } /** - * Convert a String to a byte[] object. Guards against - * null arrays and 0 length arrays. + * Convert a String to a byte[] object. Guards against null arrays and 0 + * length arrays. * @param data string to convert to a Blob - * @return Blob if data[] is non-null and {@literal length > 0}, null otherwise + * @return Blob if data[] is non-null and {@literal length > 0}, null + * otherwise */ public static byte[] stringToByteArray(String data) { if (StringUtils.isEmpty(data)) { @@ -740,8 +751,9 @@ protected static void executeCallableMode(String name, String mode, Map params) } /** - * Executes a 'lookup' query to retrieve data from the database given a list of ids. - * The query will be execute in batches of LIST_BATCH_MAX_SIZE ids each. + * Executes a 'lookup' query to retrieve data from the database given a list + * of ids. The query will be execute in batches of LIST_BATCH_MAX_SIZE ids + * each. * @param the type of the returned objects * @param * @param ids the ids to search for @@ -749,32 +761,38 @@ protected static void executeCallableMode(String name, String mode, Map params) * @param idsParameterName the name of the parameter to match the ids * @return a list of the objects found */ - protected static List findByIds(List ids, String queryName, String idsParameterName) { + protected static List findByIds(List ids, String queryName, + String idsParameterName) { return findByIds(ids, queryName, idsParameterName, new HashMap<>()); } /** * Executes an 'update' query to the database given a list of parameters. - * The query will be executed in batches of LIST_BATCH_MAX_SIZE parameters each. + * The query will be executed in batches of LIST_BATCH_MAX_SIZE parameters + * each. * @param the type of the list parameters * @param list the list of parameters to search for * @param queryName the name of the query to be executed - * @param parameterName the name of the parameter to match the parameters in the list + * @param parameterName the name of the parameter to match the parameters in + * the list * @return the count of affected rows */ @SuppressWarnings("unchecked") - protected static int udpateByIds(List list, String queryName, String parameterName, - Map parameters) { + protected static int udpateByIds(List list, String queryName, + String parameterName, Map parameters) { Query query = HibernateFactory.getSession().getNamedQuery(queryName); - parameters.entrySet().stream().forEach(entry -> query.setParameter(entry.getKey(), entry.getValue())); + parameters.entrySet().stream() + .forEach(entry -> query.setParameter(entry.getKey(), entry.getValue())); - return splitAndExecuteQuery(list, parameterName, query, query::executeUpdate, 0, Integer::sum); + return splitAndExecuteQuery(list, parameterName, query, query::executeUpdate, 0, + Integer::sum); } /** - * Executes a 'lookup' query to retrieve data from the database given a list of ids. - * The query will be execute in batches of LIST_BATCH_MAX_SIZE ids each. + * Executes a 'lookup' query to retrieve data from the database given a list + * of ids. The query will be execute in batches of LIST_BATCH_MAX_SIZE ids + * each. * @param the type of the returned objects * @param the type of the ids * @param ids the ids to search for @@ -788,20 +806,23 @@ protected static List findByIds(List ids, String queryName, String idsParameterName, Map parameters) { Query query = HibernateFactory.getSession().getNamedQuery(queryName); - parameters.entrySet().stream().forEach(entry -> query.setParameter(entry.getKey(), entry.getValue())); + parameters.entrySet().stream() + .forEach(entry -> query.setParameter(entry.getKey(), entry.getValue())); return splitAndExecuteQuery(ids, idsParameterName, query, query::getResultList, new ArrayList(), ListUtils::union); } /** - * Splits a list of elements in batches of LIST_BATCH_MAX_SIZE and execute a query for each batch. - * Results from each query are reduced via `accumulator` using the provided `identity`. + * Splits a list of elements in batches of LIST_BATCH_MAX_SIZE and execute a + * query for each batch. Results from each query are reduced via + * `accumulator` using the provided `identity`. * @param the return type * @param the type of the elements in the list parameter * @param the type of the returned objects by the query * @param list the list of parameters to search for - * @param parameterName the name of the parameter to match the parameters in the list + * @param parameterName the name of the parameter to match the parameters in + * the list * @param query the query to be executed * @param queryFunction the function to be call on the query * @param identity the identity for the accumulator function @@ -809,22 +830,23 @@ protected static List findByIds(List ids, String queryName, * @return an accumulated result of executing the query */ protected static T splitAndExecuteQuery(List list, String parameterName, - Query query, Supplier queryFunction, T identity, BinaryOperator accumulator) { + Query query, Supplier queryFunction, T identity, + BinaryOperator accumulator) { int size = list.size(); - List> batches = IntStream.iterate(0, i -> i < size, i -> i + LIST_BATCH_MAX_SIZE) + List> batches = IntStream + .iterate(0, i -> i < size, i -> i + LIST_BATCH_MAX_SIZE) .mapToObj(i -> list.subList(i, Math.min(i + LIST_BATCH_MAX_SIZE, size))) .collect(Collectors.toList()); - return batches.stream() - .map(b -> { - query.setParameterList(parameterName, b); - return queryFunction.get(); - }) - .reduce(identity, accumulator::apply); + return batches.stream().map(b -> { + query.setParameterList(parameterName, b); + return queryFunction.get(); + }).reduce(identity, accumulator::apply); } /** - * Loads the full hibernate object in case the object is currently just a proxy + * Loads the full hibernate object in case the object is currently just a + * proxy * @param proxy object to unproxy * @param type of the object to unproxy * @return the unproxied hibernate object diff --git a/java/code/src/com/redhat/rhn/domain/errata/CustomEnumType.java b/java/code/src/com/redhat/rhn/domain/errata/CustomEnumType.java index c5a23d7e96bb..9609916a201c 100644 --- a/java/code/src/com/redhat/rhn/domain/errata/CustomEnumType.java +++ b/java/code/src/com/redhat/rhn/domain/errata/CustomEnumType.java @@ -91,7 +91,6 @@ public int hashCode(Object o) throws HibernateException { return o == null ? 0 : o.hashCode(); } - @Override public void nullSafeSet(PreparedStatement statement, Object value, int position, SharedSessionContractImplementor session) throws HibernateException, SQLException { diff --git a/java/code/src/com/redhat/rhn/domain/server/ServerFactory.java b/java/code/src/com/redhat/rhn/domain/server/ServerFactory.java index e315a7076fed..6396f3aec8b3 100644 --- a/java/code/src/com/redhat/rhn/domain/server/ServerFactory.java +++ b/java/code/src/com/redhat/rhn/domain/server/ServerFactory.java @@ -211,47 +211,43 @@ public static List lookupStorageDevicesByServer(Server s) { @SuppressWarnings("unchecked") public static Optional lookupProxyServer(String name) { boolean nameIsFullyQualified = name.contains("."); - if (!nameIsFullyQualified) { - log.warn( - "Specified master name \"{}\" is not fully-qualified,proxy attachment might not be correct", - name); - log.warn("Please use a FQDN in /etc/salt/minion.d/susemanager.conf"); - } - - DetachedCriteria proxyIds = DetachedCriteria.forClass(ProxyInfo.class) - .setProjection(Projections.property("server.id")); - - Optional result = findByFqdn(name); + Optional result = Optional.empty(); + result = findByFqdn(name); if (result.isPresent()) { return result; } - result = HibernateFactory.getSession().getCriteriaBuilder() - .createQuery(Server.class).add(SYSTEM_QUERIES.propertyIn("id", proxyIds)) - .add(Restriction.eq("hostname", name)).list().stream().findFirst(); - + String sql = + "SELECT * FROM rhnServer WHERE hostname = :hostname AND id IN (SELECT server_id FROM rhnProxyInfo)"; + TypedQuery query = + HibernateFactory.getSession().createNativeQuery(sql, Server.class); + query.setParameter("hostname", name); + List servers = query.getResultList(); + result = servers.stream().findFirst(); if (result.isPresent()) { return result; } - // precise search did not work, try imprecise if (nameIsFullyQualified) { - String srippedHostname = name.split("\\.")[0]; - - return HibernateFactory.getSession().getCriteriaBuilder() - .createQuery(Server.class) - .add(SYSTEM_QUERIES.propertyIn("id", proxyIds)) - .add(Restrictions.eq("hostname", srippedHostname)).list().stream() - .findFirst(); + String strippedHostname = name.split("\\.")[0]; + sql = "SELECT * FROM rhnServer WHERE hostname = :hostname AND id IN (SELECT server_id FROM rhnProxyInfo)"; + query = HibernateFactory.getSession().createNativeQuery(sql, Server.class); + query.setParameter("hostname", strippedHostname); + servers = query.getResultList(); + result = servers.stream().findFirst(); + if (result.isPresent()) { + return result; + } } else { - return HibernateFactory.getSession().getCriteriaBuilder() - .createQuery(Server.class) - .add(SYSTEM_QUERIES.propertyIn("id", proxyIds)) - .add(Restrictions.like("hostname", name + ".", MatchMode.START)).list() - .stream().findFirst(); + sql = "SELECT * FROM rhnServer WHERE hostname LIKE :hostnamePattern AND id IN (SELECT server_id FROM rhnProxyInfo)"; + query = HibernateFactory.getSession().createNativeQuery(sql, Server.class); + query.setParameter("hostnamePattern", name + "%"); + servers = query.getResultList(); + result = servers.stream().findFirst(); } + return result; } /** @@ -788,10 +784,11 @@ public static Server lookupById(Long id) { */ @SuppressWarnings("unchecked") public static Server lookupForeignSystemByDigitalServerId(String id) { - CriteriaQuery criteria = - getSession().getCriteriaBuilder().createQuery(Server.class); - criteria.add(Restrictions.eq("digitalServerId", id)); - for (Server server : (List) criteria.list()) { + String sql = "SELECT * FROM Server WHERE rhnServer = :id"; + List servers = getSession().createNativeQuery(sql, Server.class) + .setParameter("id", id).getResultList(); + + for (Server server : servers) { if (server.hasEntitlement(EntitlementManager.getByName("foreign_entitled"))) { return server; } diff --git a/java/code/src/com/suse/cloud/domain/BillingDimensionEnumType.java b/java/code/src/com/suse/cloud/domain/BillingDimensionEnumType.java index f4f9336c97a1..c908f3c8af37 100644 --- a/java/code/src/com/suse/cloud/domain/BillingDimensionEnumType.java +++ b/java/code/src/com/suse/cloud/domain/BillingDimensionEnumType.java @@ -46,4 +46,10 @@ public int getSqlType() { return Types.OTHER; } + @Override + public void nullSafeSet(ResultSet result, int position, + SharedSessionContractImplementor session, Object value) + throws HibernateException, SQLException { + // + } }