View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.orm.jpa.vendor;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  import javax.persistence.EntityManager;
22  import javax.persistence.EntityManagerFactory;
23  import javax.persistence.spi.PersistenceProvider;
24  
25  import org.hibernate.cfg.Environment;
26  import org.hibernate.dialect.DB2Dialect;
27  import org.hibernate.dialect.DerbyDialect;
28  import org.hibernate.dialect.H2Dialect;
29  import org.hibernate.dialect.HSQLDialect;
30  import org.hibernate.dialect.InformixDialect;
31  import org.hibernate.dialect.MySQLDialect;
32  import org.hibernate.dialect.Oracle9iDialect;
33  import org.hibernate.dialect.PostgreSQLDialect;
34  import org.hibernate.dialect.SQLServerDialect;
35  
36  /**
37   * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for
38   * Hibernate EntityManager. Developed and tested against Hibernate 3.6 and 4.2/4.3.
39   * <b>Hibernate 4.2+ is strongly recommended for use with Spring 4.0+.</b>
40   *
41   * <p>Exposes Hibernate's persistence provider and EntityManager extension interface,
42   * and adapts {@link AbstractJpaVendorAdapter}'s common configuration settings.
43   * Also supports the detection of annotated packages (through
44   * {@link org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo#getManagedPackages()}),
45   * e.g. containing Hibernate {@link org.hibernate.annotations.FilterDef} annotations,
46   * along with Spring-driven entity scanning which requires no {@code persistence.xml}
47   * ({@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#setPackagesToScan}).
48   *
49   * <p>Note that the package location of Hibernate's JPA support changed from 4.2 to 4.3:
50   * from {@code org.hibernate.ejb.HibernateEntityManager(Factory)} to
51   * {@code org.hibernate.jpa.HibernateEntityManager(Factory)}. As of Spring 4.0,
52   * we're exposing the correct, non-deprecated variant depending on the Hibernate
53   * version encountered at runtime, in order to avoid deprecation log entries.
54   *
55   * @author Juergen Hoeller
56   * @author Rod Johnson
57   * @since 2.0
58   * @see HibernateJpaDialect
59   * @see org.hibernate.ejb.HibernatePersistence
60   * @see org.hibernate.ejb.HibernateEntityManager
61   */
62  public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
63  
64  	private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect();
65  
66  	private final PersistenceProvider persistenceProvider;
67  
68  	private final Class<? extends EntityManagerFactory> entityManagerFactoryInterface;
69  
70  	private final Class<? extends EntityManager> entityManagerInterface;
71  
72  
73  	@SuppressWarnings({"deprecation", "unchecked"})
74  	public HibernateJpaVendorAdapter() {
75  		ClassLoader cl = HibernateJpaVendorAdapter.class.getClassLoader();
76  		Class<? extends EntityManagerFactory> emfIfcToUse;
77  		Class<? extends EntityManager> emIfcToUse;
78  		Class<?> providerClass;
79  		PersistenceProvider providerToUse;
80  		try {
81  			try {
82  				// Try Hibernate 4.3's org.hibernate.jpa package in order to avoid deprecation warnings
83  				emfIfcToUse = (Class<? extends EntityManagerFactory>) cl.loadClass("org.hibernate.jpa.HibernateEntityManagerFactory");
84  				emIfcToUse = (Class<? extends EntityManager>) cl.loadClass("org.hibernate.jpa.HibernateEntityManager");
85  				providerClass = cl.loadClass("org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider");
86  			}
87  			catch (ClassNotFoundException ex) {
88  				// Fall back to Hibernate 3.6-4.2 org.hibernate.ejb package
89  				emfIfcToUse = (Class<? extends EntityManagerFactory>) cl.loadClass("org.hibernate.ejb.HibernateEntityManagerFactory");
90  				emIfcToUse = (Class<? extends EntityManager>) cl.loadClass("org.hibernate.ejb.HibernateEntityManager");
91  				providerClass = cl.loadClass("org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider");
92  			}
93  			providerToUse = (PersistenceProvider) providerClass.newInstance();
94  		}
95  		catch (Exception ex) {
96  			throw new IllegalStateException("Failed to determine Hibernate PersistenceProvider", ex);
97  		}
98  		this.persistenceProvider = providerToUse;
99  		this.entityManagerFactoryInterface = emfIfcToUse;
100 		this.entityManagerInterface = emIfcToUse;
101 	}
102 
103 
104 	@Override
105 	public PersistenceProvider getPersistenceProvider() {
106 		return this.persistenceProvider;
107 	}
108 
109 	@Override
110 	public String getPersistenceProviderRootPackage() {
111 		return "org.hibernate";
112 	}
113 
114 	@Override
115 	public Map<String, Object> getJpaPropertyMap() {
116 		Map<String, Object> jpaProperties = new HashMap<String, Object>();
117 
118 		if (getDatabasePlatform() != null) {
119 			jpaProperties.put(Environment.DIALECT, getDatabasePlatform());
120 		}
121 		else if (getDatabase() != null) {
122 			Class<?> databaseDialectClass = determineDatabaseDialectClass(getDatabase());
123 			if (databaseDialectClass != null) {
124 				jpaProperties.put(Environment.DIALECT, databaseDialectClass.getName());
125 			}
126 		}
127 
128 		if (isGenerateDdl()) {
129 			jpaProperties.put(Environment.HBM2DDL_AUTO, "update");
130 		}
131 		if (isShowSql()) {
132 			jpaProperties.put(Environment.SHOW_SQL, "true");
133 		}
134 
135 		return jpaProperties;
136 	}
137 
138 	/**
139 	 * Determine the Hibernate database dialect class for the given target database.
140 	 * @param database the target database
141 	 * @return the Hibernate database dialect class, or {@code null} if none found
142 	 */
143 	@SuppressWarnings("deprecation")
144 	protected Class<?> determineDatabaseDialectClass(Database database) {
145 		switch (database) {
146 			case DB2: return DB2Dialect.class;
147 			case DERBY: return DerbyDialect.class;  // DerbyDialect deprecated in 4.x
148 			case H2: return H2Dialect.class;
149 			case HSQL: return HSQLDialect.class;
150 			case INFORMIX: return InformixDialect.class;
151 			case MYSQL: return MySQLDialect.class;
152 			case ORACLE: return Oracle9iDialect.class;
153 			case POSTGRESQL: return PostgreSQLDialect.class;  // PostgreSQLDialect deprecated in 4.x
154 			case SQL_SERVER: return SQLServerDialect.class;
155 			case SYBASE: return org.hibernate.dialect.SybaseDialect.class;  // SybaseDialect deprecated in 3.6 but not 4.x
156 			default: return null;
157 		}
158 	}
159 
160 	@Override
161 	public HibernateJpaDialect getJpaDialect() {
162 		return this.jpaDialect;
163 	}
164 
165 	@Override
166 	public Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface() {
167 		return this.entityManagerFactoryInterface;
168 	}
169 
170 	@Override
171 	public Class<? extends EntityManager> getEntityManagerInterface() {
172 		return this.entityManagerInterface;
173 	}
174 
175 }