1 16 17 package org.springframework.orm.jpa; 18 19 import java.lang.reflect.InvocationHandler ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 import java.util.Map ; 26 27 import javax.persistence.EntityManager; 28 import javax.persistence.EntityManagerFactory; 29 import javax.persistence.PersistenceException; 30 import javax.persistence.Query; 31 32 import org.springframework.dao.DataAccessException; 33 import org.springframework.dao.InvalidDataAccessApiUsageException; 34 import org.springframework.util.Assert; 35 import org.springframework.util.ClassUtils; 36 37 97 public class JpaTemplate extends JpaAccessor implements JpaOperations { 98 99 private boolean exposeNativeEntityManager = false; 100 101 102 105 public JpaTemplate() { 106 } 107 108 112 public JpaTemplate(EntityManagerFactory emf) { 113 setEntityManagerFactory(emf); 114 afterPropertiesSet(); 115 } 116 117 121 public JpaTemplate(EntityManager em) { 122 setEntityManager(em); 123 afterPropertiesSet(); 124 } 125 126 127 140 public void setExposeNativeEntityManager(boolean exposeNativeEntityManager) { 141 this.exposeNativeEntityManager = exposeNativeEntityManager; 142 } 143 144 148 public boolean isExposeNativeEntityManager() { 149 return this.exposeNativeEntityManager; 150 } 151 152 153 public Object execute(JpaCallback action) throws DataAccessException { 154 return execute(action, isExposeNativeEntityManager()); 155 } 156 157 public List executeFind(JpaCallback action) throws DataAccessException { 158 Object result = execute(action, isExposeNativeEntityManager()); 159 if (!(result instanceof List )) { 160 throw new InvalidDataAccessApiUsageException( 161 "Result object returned from JpaCallback isn't a List: [" + result + "]"); 162 } 163 return (List ) result; 164 } 165 166 175 public Object execute(JpaCallback action, boolean exposeNativeEntityManager) throws DataAccessException { 176 Assert.notNull(action, "Callback object must not be null"); 177 178 EntityManager em = getEntityManager(); 179 boolean isNewEm = false; 180 if (em == null) { 181 em = getTransactionalEntityManager(); 182 if (em == null) { 183 logger.debug("Creating new EntityManager for JpaTemplate execution"); 184 em = createEntityManager(); 185 isNewEm = true; 186 } 187 } 188 189 try { 190 EntityManager emToExpose = (exposeNativeEntityManager ? em : createEntityManagerProxy(em)); 191 Object result = action.doInJpa(emToExpose); 192 flushIfNecessary(em, !isNewEm); 193 return result; 194 } 195 catch (RuntimeException ex) { 196 throw translateIfNecessary(ex); 197 } 198 finally { 199 if (isNewEm) { 200 logger.debug("Closing new EntityManager after JPA template execution"); 201 em.close(); 202 } 203 } 204 } 205 206 215 protected EntityManager createEntityManagerProxy(EntityManager em) { 216 Class [] ifcs = ClassUtils.getAllInterfaces(em); 217 return (EntityManager) Proxy.newProxyInstance( 218 getClass().getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(em)); 219 } 220 221 222 226 public <T> T find(final Class <T> entityClass, final Object id) throws DataAccessException { 227 return (T) execute(new JpaCallback() { 228 public Object doInJpa(EntityManager em) throws PersistenceException { 229 return em.find(entityClass, id); 230 } 231 }, true); 232 } 233 234 public <T> T getReference(final Class <T> entityClass, final Object id) throws DataAccessException { 235 return (T) execute(new JpaCallback() { 236 public Object doInJpa(EntityManager em) throws PersistenceException { 237 return em.getReference(entityClass, id); 238 } 239 }, true); 240 } 241 242 public boolean contains(final Object entity) throws DataAccessException { 243 Boolean result = (Boolean ) execute(new JpaCallback() { 244 public Object doInJpa(EntityManager em) throws PersistenceException { 245 return new Boolean (em.contains(entity)); 246 } 247 }, true); 248 return result.booleanValue(); 249 } 250 251 public void refresh(final Object entity) throws DataAccessException { 252 execute(new JpaCallback() { 253 public Object doInJpa(EntityManager em) throws PersistenceException { 254 em.refresh(entity); 255 return null; 256 } 257 }, true); 258 } 259 260 public void persist(final Object entity) throws DataAccessException { 261 execute(new JpaCallback() { 262 public Object doInJpa(EntityManager em) throws PersistenceException { 263 em.persist(entity); 264 return null; 265 } 266 }, true); 267 } 268 269 public <T> T merge(final T entity) throws DataAccessException { 270 return (T) execute(new JpaCallback() { 271 public Object doInJpa(EntityManager em) throws PersistenceException { 272 return em.merge(entity); 273 } 274 }, true); 275 } 276 277 public void remove(final Object entity) throws DataAccessException { 278 execute(new JpaCallback() { 279 public Object doInJpa(EntityManager em) throws PersistenceException { 280 em.remove(entity); 281 return null; 282 } 283 }, true); 284 } 285 286 public void flush() throws DataAccessException { 287 execute(new JpaCallback() { 288 public Object doInJpa(EntityManager em) throws PersistenceException { 289 em.flush(); 290 return null; 291 } 292 }, true); 293 } 294 295 296 300 public List find(String queryString) throws DataAccessException { 301 return find(queryString, (Object []) null); 302 } 303 304 public List find(final String queryString, final Object ... values) throws DataAccessException { 305 return executeFind(new JpaCallback() { 306 public Object doInJpa(EntityManager em) throws PersistenceException { 307 Query queryObject = em.createQuery(queryString); 308 if (values != null) { 309 for (int i = 0; i < values.length; i++) { 310 queryObject.setParameter(i + 1, values[i]); 311 } 312 } 313 return queryObject.getResultList(); 314 } 315 }); 316 } 317 318 public List findByNamedParams(final String queryString, final Map <String ,? extends Object > params) throws DataAccessException { 319 return executeFind(new JpaCallback() { 320 public Object doInJpa(EntityManager em) throws PersistenceException { 321 Query queryObject = em.createQuery(queryString); 322 if (params != null) { 323 for (Iterator it = params.entrySet().iterator(); it.hasNext();) { 324 Map.Entry <String , Object > entry = (Map.Entry <String , Object >) it.next(); 325 queryObject.setParameter(entry.getKey(), entry.getValue()); 326 } 327 } 328 return queryObject.getResultList(); 329 } 330 }); 331 } 332 333 public List findByNamedQuery(String queryName) throws DataAccessException { 334 return findByNamedQuery(queryName, (Object []) null); 335 } 336 337 public List findByNamedQuery(final String queryName, final Object ... values) throws DataAccessException { 338 return executeFind(new JpaCallback() { 339 public Object doInJpa(EntityManager em) throws PersistenceException { 340 Query queryObject = em.createNamedQuery(queryName); 341 if (values != null) { 342 for (int i = 0; i < values.length; i++) { 343 queryObject.setParameter(i + 1, values[i]); 344 } 345 } 346 return queryObject.getResultList(); 347 } 348 }); 349 } 350 351 public List findByNamedQueryAndNamedParams(final String queryName, final Map <String , ? extends Object > params) 352 throws DataAccessException { 353 354 return executeFind(new JpaCallback() { 355 public Object doInJpa(EntityManager em) throws PersistenceException { 356 Query queryObject = em.createNamedQuery(queryName); 357 if (params != null) { 358 for (Iterator it = params.entrySet().iterator(); it.hasNext();) { 359 Map.Entry <String , Object > entry = (Map.Entry <String , Object >) it.next(); 360 queryObject.setParameter(entry.getKey(), entry.getValue()); 361 } 362 } 363 return queryObject.getResultList(); 364 } 365 }); 366 } 367 368 369 374 private class CloseSuppressingInvocationHandler implements InvocationHandler { 375 376 private final EntityManager target; 377 378 public CloseSuppressingInvocationHandler(EntityManager target) { 379 this.target = target; 380 } 381 382 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 383 385 if (method.getName().equals("equals")) { 386 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); 388 } 389 else if (method.getName().equals("hashCode")) { 390 return new Integer (hashCode()); 392 } 393 else if (method.getName().equals("close")) { 394 return null; 396 } 397 398 try { 400 return method.invoke(this.target, args); 401 } 402 catch (InvocationTargetException ex) { 403 throw ex.getTargetException(); 404 } 405 } 406 } 407 408 } 409 | Popular Tags |