blob: 8efd1ab54c89230eca7c11654d967f40ddab507a [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jpa;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Query;
import org.eclipse.persistence.internal.jpa.*;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.server.Server;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.sessions.broker.SessionBroker;
import org.eclipse.persistence.sessions.factories.SessionFactory;
import org.eclipse.persistence.queries.FetchGroupTracker;
/**
* This sample illustrates the JPA helper methods that may be of use
* to EclipseLink customers attempting to leverage EclipseLink specific functionality.
*
* @author dclarke, gpelletie
*/
public class JpaHelper {
private JpaHelper() {
}
/**
* Verify if the JPA provider is EclipseLink. If you are in a container
* and not in a transaction this method may incorrectly return false.
* It is always more reliable to check isEclipseLink on the EMF or Query.
*/
public static boolean isEclipseLink(jakarta.persistence.EntityManager em) {
return getEntityManager(em) != null;
}
/**
* Verify if the JPA provider is EclipseLink
*/
public static boolean isEclipseLink(EntityManagerFactory emf) {
try {
getEntityManagerFactory(emf);
} catch (IllegalArgumentException iae) {
return false;
}
return true;
}
/**
* Verify if the JPA provider is EclipseLink
*/
public static boolean isEclipseLink(Query query) {
return query instanceof JpaQuery;
}
/**
* Determine if the JPA query is a EclipseLink ReportQuery. Useful for
* frameworks that want to determine which get_X_Query method they can
* safely invoke.
*/
public static boolean isReportQuery(Query query) {
return isEclipseLink(query) && getDatabaseQuery(query).isReportQuery();
}
/**
* Access the internal EclipseLink query wrapped within the JPA query. A
* EclipseLink JPA created from JP QL contains a ReportQuery if multiple
* items or a non-entity type is being returned. This method will fail
* if a single entity type is being returned as the query is a ReadAllQuery.
*
* @see JpaHelper#getReadAllQuery
*/
public static ReportQuery getReportQuery(Query query) {
DatabaseQuery dbQuery = getDatabaseQuery(query);
if (dbQuery.isReportQuery()) {
return (ReportQuery)dbQuery;
}
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_helper_invalid_report_query" + query.getClass()));
}
/**
* Access the internal EclipseLink query wrapped within the JPA query.
*/
public static DatabaseQuery getDatabaseQuery(Query query) {
if (query instanceof JpaQuery) {
return ((JpaQuery)query).getDatabaseQuery();
}
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_helper_invalid_query" + query.getClass()));
}
/**
* Access the internal EclipseLink query wrapped within the JPA query. A EclipseLink
* JPA created from JP QL only contains a ReadAllQuery if only a single entity
* type is being returned.
*
* A ReadAllQuery is the super class of a ReportQuery so this method will
* always work for either a ReportQuery or ReadAllQuery.
*/
public static ReadAllQuery getReadAllQuery(Query query) {
DatabaseQuery dbQuery = getDatabaseQuery(query);
if (dbQuery.isReadAllQuery()) {
return (ReadAllQuery)dbQuery;
}
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_helper_invalid_read_all_query" + query.getClass()));
}
/**
* Create a EclipseLink JPA query dynamically given a EclipseLink query.
*/
public static Query createQuery(DatabaseQuery query, jakarta.persistence.EntityManager em) {
return getEntityManager(em).createQuery(query);
}
/**
* Convert a JPA entityManager into a EclipseLink specific one. This will work
* both within a JavaSE deployment as well as within a container where the
* EntityManager may be wrapped.
*
* In the case where the container is not in a transaction it may return null
* for its delegate. When this happens the only way to access an EntityManager
* is to use the EntityManagerFactory to create a temporary one where the
* application manage its lifecycle.
*/
public static JpaEntityManager getEntityManager(jakarta.persistence.EntityManager entityManager) {
if (entityManager instanceof JpaEntityManager) {
return (JpaEntityManager)entityManager;
}
if (entityManager.getDelegate() != null) {
return getEntityManager((jakarta.persistence.EntityManager)entityManager.getDelegate());
}
return null;
}
/**
* Given a JPA EntityManagerFactory attempt to cast it to a EclipseLink EMF.
*
* Although this method currently returns an instance of EntityManagerFactoryImpl, it
* is recommended that users cast to JpaEntityManagerFactory. Future versions of EclipseLink will
* return that interface from this method instead
*
* @see JpaEntityManagerFactory
* @deprecated
*/
@Deprecated
public static EntityManagerFactoryImpl getEntityManagerFactory(EntityManagerFactoryImpl emf) {
return (emf);
}
/**
* Given a JPA EntityManagerFactory attempt to cast it to a EclipseLink EMF.
*
* @see JpaEntityManagerFactory
*/
public static JpaEntityManagerFactory getEntityManagerFactory(EntityManagerFactory emf) {
if (emf instanceof JpaEntityManagerFactory) {
return ((JpaEntityManagerFactory)emf);
}
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_helper_invalid_entity_manager_factory", new Object[]{emf.getClass()}));
}
/**
* Given an EntityManager return the EntityManagerFactory that created it. This method must be called
* on an open entity manager and will return null if called on a closed entityManager.
*
* This method will return null for non-EclipseLink EntityManagers.
*
* @see JpaEntityManagerFactory
*/
public static JpaEntityManagerFactory getEntityManagerFactory(jakarta.persistence.EntityManager em) {
JpaEntityManager entityManager = getEntityManager(em);
if (entityManager != null){
if (entityManager.getEntityManagerFactory() != null){
return ((EntityManagerFactoryDelegate)entityManager.getEntityManagerFactory()).getOwner();
}
}
return null;
}
/**
* Retrieve the shared database session from the EMF.
*/
public static DatabaseSession getDatabaseSession(EntityManagerFactory emf) {
return getEntityManagerFactory(emf).getDatabaseSession();
}
/**
* Retrieve the shared server session from the EMF.
*/
public static Server getServerSession(EntityManagerFactory emf) {
return getEntityManagerFactory(emf).getServerSession();
}
/**
* Retrieve the shared session broker from the EMF.
*/
public static SessionBroker getSessionBroker(EntityManagerFactory emf) {
return getEntityManagerFactory(emf).getSessionBroker();
}
/**
* Create a EclipseLink EMF given a ServerSession that has already been created
* and logged in.
*/
public static jakarta.persistence.EntityManagerFactory createEntityManagerFactory(Server session) {
return new EntityManagerFactoryImpl((ServerSession)session);
}
/**
* Create a EclipseLink EMF using a session name and sessions.xml. This is
* equivalent to using the EclipseLink.session-xml and EclipseLink.session-name PU
* properties with the exception that no persistence.xml is required.
*
* The application would be required to manage this singleton EMF.
*/
public static EntityManagerFactory createEntityManagerFactory(String sessionName) {
SessionFactory sf = new SessionFactory(sessionName);
// Verify that shared session is a ServerSession
return new EntityManagerFactoryImpl((ServerSession)sf.getSharedSession());
}
/**
* If the object has a fetch group then the whole object is read in.
*/
public static void loadUnfetchedObject(FetchGroupTracker entity) {
if(entity._persistence_getFetchGroup() != null) {
EntityManagerImpl.processUnfetchedAttribute(entity, null);
}
}
}