001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.orm.jpa; 018 019import java.io.Serializable; 020import java.sql.SQLException; 021 022import javax.persistence.EntityManager; 023import javax.persistence.PersistenceException; 024 025import org.springframework.dao.DataAccessException; 026import org.springframework.jdbc.datasource.ConnectionHandle; 027import org.springframework.lang.Nullable; 028import org.springframework.transaction.InvalidIsolationLevelException; 029import org.springframework.transaction.TransactionDefinition; 030import org.springframework.transaction.TransactionException; 031 032/** 033 * Default implementation of the {@link JpaDialect} interface. 034 * Used as default dialect by {@link JpaTransactionManager}. 035 * 036 * <p>Simply begins a standard JPA transaction in {@link #beginTransaction} and 037 * performs standard exception translation through {@link EntityManagerFactoryUtils}. 038 * 039 * <p><b>NOTE: Spring's JPA support requires JPA 2.1 or higher, as of Spring 5.0.</b> 040 * 041 * @author Juergen Hoeller 042 * @since 2.0 043 * @see JpaTransactionManager#setJpaDialect 044 */ 045@SuppressWarnings("serial") 046public class DefaultJpaDialect implements JpaDialect, Serializable { 047 048 /** 049 * This implementation invokes the standard JPA {@code Transaction.begin} 050 * method. Throws an InvalidIsolationLevelException if a non-default isolation 051 * level is set. 052 * <p>This implementation does not return any transaction data Object, since there 053 * is no state to be kept for a standard JPA transaction. Hence, subclasses do not 054 * have to care about the return value ({@code null}) of this implementation 055 * and are free to return their own transaction data Object. 056 * @see javax.persistence.EntityTransaction#begin 057 * @see org.springframework.transaction.InvalidIsolationLevelException 058 * @see #cleanupTransaction 059 */ 060 @Override 061 @Nullable 062 public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) 063 throws PersistenceException, SQLException, TransactionException { 064 065 if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { 066 throw new InvalidIsolationLevelException(getClass().getSimpleName() + 067 " does not support custom isolation levels due to limitations in standard JPA. " + 068 "Specific arrangements may be implemented in custom JpaDialect variants."); 069 } 070 entityManager.getTransaction().begin(); 071 return null; 072 } 073 074 @Override 075 @Nullable 076 public Object prepareTransaction(EntityManager entityManager, boolean readOnly, @Nullable String name) 077 throws PersistenceException { 078 079 return null; 080 } 081 082 /** 083 * This implementation does nothing, since the default {@code beginTransaction} 084 * implementation does not require any cleanup. 085 * @see #beginTransaction 086 */ 087 @Override 088 public void cleanupTransaction(@Nullable Object transactionData) { 089 } 090 091 /** 092 * This implementation always returns {@code null}, 093 * indicating that no JDBC Connection can be provided. 094 */ 095 @Override 096 @Nullable 097 public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) 098 throws PersistenceException, SQLException { 099 100 return null; 101 } 102 103 /** 104 * This implementation does nothing, assuming that the Connection 105 * will implicitly be closed with the EntityManager. 106 * <p>If the JPA implementation returns a Connection handle that it expects 107 * the application to close after use, the dialect implementation needs to invoke 108 * {@code Connection.close()} (or some other method with similar effect) here. 109 * @see java.sql.Connection#close() 110 */ 111 @Override 112 public void releaseJdbcConnection(ConnectionHandle conHandle, EntityManager em) 113 throws PersistenceException, SQLException { 114 } 115 116 117 //----------------------------------------------------------------------------------- 118 // Hook for exception translation (used by JpaTransactionManager) 119 //----------------------------------------------------------------------------------- 120 121 /** 122 * This implementation delegates to EntityManagerFactoryUtils. 123 * @see EntityManagerFactoryUtils#convertJpaAccessExceptionIfPossible 124 */ 125 @Override 126 @Nullable 127 public DataAccessException translateExceptionIfPossible(RuntimeException ex) { 128 return EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex); 129 } 130 131}