1 16 17 package org.springframework.orm.hibernate3; 18 19 import java.io.File ; 20 import java.lang.reflect.Array ; 21 import java.sql.Connection ; 22 import java.sql.SQLException ; 23 import java.sql.Statement ; 24 import java.util.Collection ; 25 import java.util.Enumeration ; 26 import java.util.Iterator ; 27 import java.util.Map ; 28 import java.util.Properties ; 29 30 import javax.sql.DataSource ; 31 import javax.transaction.TransactionManager ; 32 33 import org.hibernate.ConnectionReleaseMode; 34 import org.hibernate.HibernateException; 35 import org.hibernate.Interceptor; 36 import org.hibernate.Session; 37 import org.hibernate.SessionFactory; 38 import org.hibernate.cfg.Configuration; 39 import org.hibernate.cfg.Environment; 40 import org.hibernate.cfg.Mappings; 41 import org.hibernate.cfg.NamingStrategy; 42 import org.hibernate.dialect.Dialect; 43 import org.hibernate.engine.FilterDefinition; 44 import org.hibernate.event.EventListeners; 45 import org.hibernate.tool.hbm2ddl.DatabaseMetadata; 46 import org.hibernate.transaction.JTATransactionFactory; 47 48 import org.springframework.beans.BeanUtils; 49 import org.springframework.core.io.ClassPathResource; 50 import org.springframework.core.io.Resource; 51 import org.springframework.dao.DataAccessException; 52 import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; 53 import org.springframework.jdbc.support.JdbcUtils; 54 import org.springframework.jdbc.support.lob.LobHandler; 55 import org.springframework.util.Assert; 56 import org.springframework.util.StringUtils; 57 58 108 public class LocalSessionFactoryBean extends AbstractSessionFactoryBean { 109 110 private static final ThreadLocal configTimeDataSourceHolder = new ThreadLocal (); 111 112 private static final ThreadLocal configTimeTransactionManagerHolder = new ThreadLocal (); 113 114 private static final ThreadLocal configTimeLobHandlerHolder = new ThreadLocal (); 115 116 125 public static DataSource getConfigTimeDataSource() { 126 return (DataSource ) configTimeDataSourceHolder.get(); 127 } 128 129 138 public static TransactionManager getConfigTimeTransactionManager() { 139 return (TransactionManager ) configTimeTransactionManagerHolder.get(); 140 } 141 142 153 public static LobHandler getConfigTimeLobHandler() { 154 return (LobHandler) configTimeLobHandlerHolder.get(); 155 } 156 157 158 private Class configurationClass = Configuration.class; 159 160 private Resource[] configLocations; 161 162 private Resource[] mappingLocations; 163 164 private Resource[] cacheableMappingLocations; 165 166 private Resource[] mappingJarLocations; 167 168 private Resource[] mappingDirectoryLocations; 169 170 private Properties hibernateProperties; 171 172 private DataSource dataSource; 173 174 private boolean useTransactionAwareDataSource = false; 175 176 private TransactionManager jtaTransactionManager; 177 178 private LobHandler lobHandler; 179 180 private Interceptor entityInterceptor; 181 182 private NamingStrategy namingStrategy; 183 184 private TypeDefinitionBean[] typeDefinitions; 185 186 private FilterDefinition[] filterDefinitions; 187 188 private Properties entityCacheStrategies; 189 190 private Properties collectionCacheStrategies; 191 192 private Map eventListeners; 193 194 private boolean schemaUpdate = false; 195 196 private Configuration configuration; 197 198 199 214 public void setConfigurationClass(Class configurationClass) { 215 if (configurationClass == null || !Configuration.class.isAssignableFrom(configurationClass)) { 216 throw new IllegalArgumentException ( 217 "configurationClass must be assignable to [org.hibernate.cfg.Configuration]"); 218 } 219 this.configurationClass = configurationClass; 220 } 221 222 229 public void setConfigLocation(Resource configLocation) { 230 this.configLocations = new Resource[] {configLocation}; 231 } 232 233 240 public void setConfigLocations(Resource[] configLocations) { 241 this.configLocations = configLocations; 242 } 243 244 254 public void setMappingResources(String [] mappingResources) { 255 this.mappingLocations = new Resource[mappingResources.length]; 256 for (int i = 0; i < mappingResources.length; i++) { 257 this.mappingLocations[i] = new ClassPathResource(mappingResources[i].trim()); 258 } 259 } 260 261 270 public void setMappingLocations(Resource[] mappingLocations) { 271 this.mappingLocations = mappingLocations; 272 } 273 274 283 public void setCacheableMappingLocations(Resource[] cacheableMappingLocations) { 284 this.cacheableMappingLocations = cacheableMappingLocations; 285 } 286 287 294 public void setMappingJarLocations(Resource[] mappingJarLocations) { 295 this.mappingJarLocations = mappingJarLocations; 296 } 297 298 305 public void setMappingDirectoryLocations(Resource[] mappingDirectoryLocations) { 306 this.mappingDirectoryLocations = mappingDirectoryLocations; 307 } 308 309 318 public void setHibernateProperties(Properties hibernateProperties) { 319 this.hibernateProperties = hibernateProperties; 320 } 321 322 326 public Properties getHibernateProperties() { 327 if (this.hibernateProperties == null) { 328 this.hibernateProperties = new Properties (); 329 } 330 return this.hibernateProperties; 331 } 332 333 354 public void setDataSource(DataSource dataSource) { 355 this.dataSource = dataSource; 356 } 357 358 402 public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) { 403 this.useTransactionAwareDataSource = useTransactionAwareDataSource; 404 } 405 406 415 public void setJtaTransactionManager(TransactionManager jtaTransactionManager) { 416 this.jtaTransactionManager = jtaTransactionManager; 417 } 418 419 428 public void setLobHandler(LobHandler lobHandler) { 429 this.lobHandler = lobHandler; 430 } 431 432 446 public void setEntityInterceptor(Interceptor entityInterceptor) { 447 this.entityInterceptor = entityInterceptor; 448 } 449 450 455 public void setNamingStrategy(NamingStrategy namingStrategy) { 456 this.namingStrategy = namingStrategy; 457 } 458 459 468 public void setTypeDefinitions(TypeDefinitionBean[] typeDefinitions) { 469 this.typeDefinitions = typeDefinitions; 470 } 471 472 482 public void setFilterDefinitions(FilterDefinition[] filterDefinitions) { 483 this.filterDefinitions = filterDefinitions; 484 } 485 486 504 public void setEntityCacheStrategies(Properties entityCacheStrategies) { 505 this.entityCacheStrategies = entityCacheStrategies; 506 } 507 508 526 public void setCollectionCacheStrategies(Properties collectionCacheStrategies) { 527 this.collectionCacheStrategies = collectionCacheStrategies; 528 } 529 530 542 public void setEventListeners(Map eventListeners) { 543 this.eventListeners = eventListeners; 544 } 545 546 554 public void setSchemaUpdate(boolean schemaUpdate) { 555 this.schemaUpdate = schemaUpdate; 556 } 557 558 559 protected SessionFactory buildSessionFactory() throws Exception { 560 Configuration config = newConfiguration(); 562 563 if (this.dataSource != null) { 564 configTimeDataSourceHolder.set(this.dataSource); 566 } 567 568 if (this.jtaTransactionManager != null) { 569 configTimeTransactionManagerHolder.set(this.jtaTransactionManager); 571 } 572 573 if (this.lobHandler != null) { 574 configTimeLobHandlerHolder.set(this.lobHandler); 577 } 578 579 try { 580 if (this.jtaTransactionManager != null) { 581 config.setProperty( 583 Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName()); 584 config.setProperty( 585 Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName()); 586 } 587 else { 588 config.setProperty(Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.ON_CLOSE.toString()); 594 } 595 596 if (!isExposeTransactionAwareSessionFactory()) { 597 config.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, 602 "org.springframework.orm.hibernate3.SpringSessionContext"); 603 } 604 605 if (this.entityInterceptor != null) { 606 config.setInterceptor(this.entityInterceptor); 608 } 609 610 if (this.namingStrategy != null) { 611 config.setNamingStrategy(this.namingStrategy); 613 } 614 615 if (this.typeDefinitions != null) { 616 Mappings mappings = config.createMappings(); 618 for (int i = 0; i < this.typeDefinitions.length; i++) { 619 TypeDefinitionBean typeDef = this.typeDefinitions[i]; 620 mappings.addTypeDef(typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters()); 621 } 622 } 623 624 if (this.filterDefinitions != null) { 625 for (int i = 0; i < this.filterDefinitions.length; i++) { 627 config.addFilterDefinition(this.filterDefinitions[i]); 628 } 629 } 630 631 if (this.configLocations != null) { 632 for (int i = 0; i < this.configLocations.length; i++) { 633 config.configure(this.configLocations[i].getURL()); 635 } 636 } 637 638 if (this.hibernateProperties != null) { 639 config.addProperties(this.hibernateProperties); 641 } 642 643 if (this.dataSource != null) { 644 boolean actuallyTransactionAware = 645 (this.useTransactionAwareDataSource || this.dataSource instanceof TransactionAwareDataSourceProxy); 646 config.setProperty(Environment.CONNECTION_PROVIDER, 648 actuallyTransactionAware ? 649 TransactionAwareDataSourceConnectionProvider.class.getName() : 650 LocalDataSourceConnectionProvider.class.getName()); 651 } 652 653 if (this.mappingLocations != null) { 654 for (int i = 0; i < this.mappingLocations.length; i++) { 656 config.addInputStream(this.mappingLocations[i].getInputStream()); 657 } 658 } 659 660 if (this.cacheableMappingLocations != null) { 661 for (int i = 0; i < this.cacheableMappingLocations.length; i++) { 663 config.addCacheableFile(this.cacheableMappingLocations[i].getFile()); 664 } 665 } 666 667 if (this.mappingJarLocations != null) { 668 for (int i = 0; i < this.mappingJarLocations.length; i++) { 670 Resource resource = this.mappingJarLocations[i]; 671 config.addJar(resource.getFile()); 672 } 673 } 674 675 if (this.mappingDirectoryLocations != null) { 676 for (int i = 0; i < this.mappingDirectoryLocations.length; i++) { 678 File file = this.mappingDirectoryLocations[i].getFile(); 679 if (!file.isDirectory()) { 680 throw new IllegalArgumentException ( 681 "Mapping directory location [" + this.mappingDirectoryLocations[i] + 682 "] does not denote a directory"); 683 } 684 config.addDirectory(file); 685 } 686 } 687 688 if (this.entityCacheStrategies != null) { 689 for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) { 691 String className = (String ) classNames.nextElement(); 692 String [] strategyAndRegion = 693 StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className)); 694 if (strategyAndRegion.length > 1) { 695 config.setCacheConcurrencyStrategy(className, strategyAndRegion[0], strategyAndRegion[1]); 696 } 697 else if (strategyAndRegion.length > 0) { 698 config.setCacheConcurrencyStrategy(className, strategyAndRegion[0]); 699 } 700 } 701 } 702 703 if (this.collectionCacheStrategies != null) { 704 for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) { 706 String collRole = (String ) collRoles.nextElement(); 707 String [] strategyAndRegion = 708 StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole)); 709 if (strategyAndRegion.length > 1) { 710 config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]); 711 } 712 else if (strategyAndRegion.length > 0) { 713 config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]); 714 } 715 } 716 } 717 718 if (this.eventListeners != null) { 719 for (Iterator it = this.eventListeners.entrySet().iterator(); it.hasNext();) { 721 Map.Entry entry = (Map.Entry ) it.next(); 722 Assert.isTrue(entry.getKey() instanceof String , "Event listener key needs to be of type String"); 723 String listenerType = (String ) entry.getKey(); 724 Object listenerObject = entry.getValue(); 725 if (listenerObject instanceof Collection ) { 726 Collection listeners = (Collection ) listenerObject; 727 EventListeners listenerRegistry = config.getEventListeners(); 728 Object [] listenerArray = 729 (Object []) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size()); 730 listenerArray = listeners.toArray(listenerArray); 731 config.setListeners(listenerType, listenerArray); 732 } 733 else { 734 config.setListener(listenerType, listenerObject); 735 } 736 } 737 } 738 739 postProcessConfiguration(config); 741 742 logger.info("Building new Hibernate SessionFactory"); 744 this.configuration = config; 745 return newSessionFactory(config); 746 } 747 748 finally { 749 if (this.dataSource != null) { 750 configTimeDataSourceHolder.set(null); 752 } 753 754 if (this.jtaTransactionManager != null) { 755 configTimeTransactionManagerHolder.set(null); 757 } 758 759 if (this.lobHandler != null) { 760 configTimeLobHandlerHolder.set(null); 762 } 763 } 764 } 765 766 778 protected Configuration newConfiguration() throws HibernateException { 779 return (Configuration) BeanUtils.instantiateClass(this.configurationClass); 780 } 781 782 789 protected void postProcessConfiguration(Configuration config) throws HibernateException { 790 } 791 792 804 protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { 805 return config.buildSessionFactory(); 806 } 807 808 813 public final Configuration getConfiguration() { 814 if (this.configuration == null) { 815 throw new IllegalStateException ("Configuration not initialized yet"); 816 } 817 return this.configuration; 818 } 819 820 825 protected void afterSessionFactoryCreation() throws Exception { 826 if (this.schemaUpdate) { 827 if (this.dataSource != null) { 828 configTimeDataSourceHolder.set(this.dataSource); 831 } 832 try { 833 updateDatabaseSchema(); 834 } 835 finally { 836 if (this.dataSource != null) { 837 configTimeDataSourceHolder.set(null); 839 } 840 } 841 } 842 } 843 844 847 public void destroy() throws HibernateException { 848 if (this.dataSource != null) { 849 configTimeDataSourceHolder.set(this.dataSource); 852 } 853 try { 854 super.destroy(); 855 } 856 finally { 857 if (this.dataSource != null) { 858 configTimeDataSourceHolder.set(null); 860 } 861 } 862 } 863 864 865 878 public void dropDatabaseSchema() throws DataAccessException { 879 logger.info("Dropping database schema for Hibernate SessionFactory"); 880 HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); 881 hibernateTemplate.execute( 882 new HibernateCallback() { 883 public Object doInHibernate(Session session) throws HibernateException, SQLException { 884 Connection con = session.connection(); 885 Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); 886 String [] sql = getConfiguration().generateDropSchemaScript(dialect); 887 executeSchemaScript(con, sql); 888 return null; 889 } 890 } 891 ); 892 } 893 894 907 public void createDatabaseSchema() throws DataAccessException { 908 logger.info("Creating database schema for Hibernate SessionFactory"); 909 HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); 910 hibernateTemplate.execute( 911 new HibernateCallback() { 912 public Object doInHibernate(Session session) throws HibernateException, SQLException { 913 Connection con = session.connection(); 914 Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); 915 String [] sql = getConfiguration().generateSchemaCreationScript(dialect); 916 executeSchemaScript(con, sql); 917 return null; 918 } 919 } 920 ); 921 } 922 923 938 public void updateDatabaseSchema() throws DataAccessException { 939 logger.info("Updating database schema for Hibernate SessionFactory"); 940 HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); 941 hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER); 942 hibernateTemplate.execute( 943 new HibernateCallback() { 944 public Object doInHibernate(Session session) throws HibernateException, SQLException { 945 Connection con = session.connection(); 946 Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); 947 DatabaseMetadata metadata = new DatabaseMetadata(con, dialect); 948 String [] sql = getConfiguration().generateSchemaUpdateScript(dialect, metadata); 949 executeSchemaScript(con, sql); 950 return null; 951 } 952 } 953 ); 954 } 955 956 966 protected void executeSchemaScript(Connection con, String [] sql) throws SQLException { 967 if (sql != null && sql.length > 0) { 968 boolean oldAutoCommit = con.getAutoCommit(); 969 if (!oldAutoCommit) { 970 con.setAutoCommit(true); 971 } 972 try { 973 Statement stmt = con.createStatement(); 974 try { 975 for (int i = 0; i < sql.length; i++) { 976 executeSchemaStatement(stmt, sql[i]); 977 } 978 } 979 finally { 980 JdbcUtils.closeStatement(stmt); 981 } 982 } 983 finally { 984 if (!oldAutoCommit) { 985 con.setAutoCommit(false); 986 } 987 } 988 } 989 } 990 991 999 protected void executeSchemaStatement(Statement stmt, String sql) throws SQLException { 1000 if (logger.isDebugEnabled()) { 1001 logger.debug("Executing schema statement: " + sql); 1002 } 1003 try { 1004 stmt.executeUpdate(sql); 1005 } 1006 catch (SQLException ex) { 1007 if (logger.isWarnEnabled()) { 1008 logger.warn("Unsuccessful schema statement: " + sql, ex); 1009 } 1010 } 1011 } 1012 1013} 1014 | Popular Tags |