2011-05-29 66 views
0

我有两个持久化类:User.java,Role.java,这些都在hibernate.cfg.xml中声明。我正在使用春天。 applicationContext.xml文件有:基于hibernate注释类创建数据库模式

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 
<bean id="dataSource" class="info.ems.datasource.DataSourceFactory"> 
    <property name="driverClassName" value="${database.driver}"/> 
    <property name="url" value="${database.url}"/> 
    <property name="username" value="${database.username}"/> 
    <property name="password" value="${database.password}"/> 
    <property name="validationQuery" value="${database.validationQuery}"/> 
    <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> 
</bean>  
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="configLocation"> 
     <value>/WEB-INF/hibernate.cfg.xml</value> 
    </property> 
    <property name="configurationClass"> 
     <value>org.hibernate.cfg.AnnotationConfiguration</value> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${hibernate.dialect}</prop>   
      <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>  
     </props> 
    </property> 
</bean> 
<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema"> 
    <property name="hibernateTemplate"> 
     <bean class="org.springframework.orm.hibernate3.HibernateTemplate"> 
      <property name="sessionFactory" ref="sessionFactory"/> 
      <property name="flushMode"> 
       <bean id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_COMMIT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>      
      </property> 
     </bean> 
    </property> 
    <property name="schemaHelper"> 
     <bean class="info.ems.hibernate.SchemaHelper">     
      <property name="driverClassName" value="${database.driver}"/> 
      <property name="url" value="${database.url}"/> 
      <property name="username" value="${database.username}"/> 
      <property name="password" value="${database.password}"/> 
      <property name="hibernateDialect" value="${hibernate.dialect}"/> 
      <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> 
     </bean>     
    </property>    
</bean>  

的DataSourceFactory.java:

public class DataSourceFactory implements FactoryBean, DisposableBean { 

    /** The logger. */ 
    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    /** The driver class name. */ 
    private String driverClassName; 

    /** The url. */ 
    private String url; 

    /** The username. */ 
    private String username; 

    /** The password. */ 
    private String password; 

    /** The validation query. */ 
    private String validationQuery; 

    /** The data source jndi name. */ 
    private String dataSourceJndiName; 

    /** The data source. */ 
    private DataSource dataSource; 

    /** 
    * Sets the driver class name. 
    * 
    * @param driverClassName 
    *   the new driver class name 
    */ 
    public void setDriverClassName(String driverClassName) { 
     this.driverClassName = driverClassName; 
    } 

    /** 
    * Sets the url. 
    * 
    * @param url 
    *   the new url 
    */ 
    public void setUrl(String url) { 
     this.url = url; 
    } 

    /** 
    * Sets the username. 
    * 
    * @param username 
    *   the new username 
    */ 
    public void setUsername(String username) { 
     this.username = username; 
    } 

    /** 
    * Sets the password. 
    * 
    * @param password 
    *   the new password 
    */ 
    public void setPassword(String password) { 
     this.password = password; 
    } 

    /** 
    * Sets the validation query. 
    * 
    * @param validationQuery 
    *   the new validation query 
    */ 
    public void setValidationQuery(String validationQuery) { 
     this.validationQuery = validationQuery; 
    } 

    /** 
    * Sets the data source jndi name. 
    * 
    * @param dataSourceJndiName 
    *   the new data source jndi name 
    */ 
    public void setDataSourceJndiName(String dataSourceJndiName) { 
     this.dataSourceJndiName = dataSourceJndiName; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.beans.factory.FactoryBean#getObject() 
    */ 
    @Override 
    public Object getObject() throws Exception { 
     if (StringUtils.hasText(dataSourceJndiName)) { 
      logger.info("JNDI datasource requested, looking up datasource from JNDI name: '" + dataSourceJndiName + "'."); 
      JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean(); 
      jndiObjectFactoryBean.setJndiName(dataSourceJndiName); 
      jndiObjectFactoryBean.setResourceRef(true); 
      try { 
       jndiObjectFactoryBean.afterPropertiesSet(); 
      } catch (Exception e) { 
       logger.error("datasource init from JNDI failed : " + e); 
       logger.error("Aborting application startup."); 
       throw new RuntimeException(e); 
      } 
      dataSource = (DataSource) jndiObjectFactoryBean.getObject(); 
     } else if (url.startsWith("jdbc:hsqldb:file")) { 
      logger.info("Embedded HSQLDB mode detected, switching on spring single connection data source."); 
      SingleConnectionDataSource singleConnectionDataSource = new SingleConnectionDataSource(); 
      singleConnectionDataSource.setUrl(url); 
      singleConnectionDataSource.setDriverClassName(driverClassName); 
      singleConnectionDataSource.setUsername(username); 
      singleConnectionDataSource.setPassword(password); 
      singleConnectionDataSource.setSuppressClose(true); 
      dataSource = singleConnectionDataSource; 
     } else { 
      logger.info("Not using embedded HSQLDB or JNDI datasource, switching on Apache DBCP data source connection pooling."); 
      BasicDataSource basicDataSource = new BasicDataSource(); 
      basicDataSource.setUrl(url); 
      basicDataSource.setDriverClassName(driverClassName); 
      basicDataSource.setUsername(username); 
      basicDataSource.setPassword(password); 
      basicDataSource.setValidationQuery(validationQuery); 
      basicDataSource.setTestOnBorrow(false); 
      basicDataSource.setTestWhileIdle(true); 
      basicDataSource.setTimeBetweenEvictionRunsMillis(600000); 
      dataSource = basicDataSource; 
     } 
     return dataSource; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.beans.factory.FactoryBean#getObjectType() 
    */ 
    @Override 
    public Class<?> getObjectType() { 
     return DataSource.class; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.beans.factory.FactoryBean#isSingleton() 
    */ 
    @Override 
    public boolean isSingleton() { 
     return true; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.beans.factory.DisposableBean#destroy() 
    */ 
    @Override 
    public void destroy() throws Exception { 
     if (dataSource instanceof SingleConnectionDataSource) { 
      logger.info("Attempting to shut down embedded HSQLDB database."); 
      Connection connection = dataSource.getConnection(); 
      Statement statement = connection.createStatement(); 
      statement.executeUpdate("SHUTDOWN"); 
      statement.close(); 
      connection.close(); 
      logger.info("Embedded HSQLDB database shut down successfully."); 
     } else if (dataSource instanceof BasicDataSource) { 
      logger.info("Attempting to close Apache DBCP data source."); 
      ((BasicDataSource) dataSource).close(); 
      logger.info("Apache DBCP data source closed successfully."); 
     } else { 
      logger.info("Context shutting down for JNDI datasource."); 
     } 
    } 
} 

的HibernateEMSDao.java:

public class HibernateEMSDao extends HibernateDaoSupport implements EMSDao { 

    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    private SchemaHelper schemaHelper; 

    public void setSchemaHelper(SchemaHelper schemaHelper) { 
     this.schemaHelper = schemaHelper; 
    } 

    public void storeUser(User user) { 
     getHibernateTemplate().merge(user); 
    } 

    public void createSchema() { 
     try { 
      getHibernateTemplate().find("from User user where user.id = 1"); 
     } catch (Exception e) { 
      logger.warn("expected database schema does not exist, will create. Error is: " + e.getMessage()); 
      schemaHelper.createSchema(); 
      User admin = new User(); 
      admin.setUsername("admin"); 
      admin.setName("Admin"); 
      admin.setEmail("admin"); 
      admin.setPassword("21232f297a57a5a743894a0e4a801fc3");   
      logger.info("inserting default admin user into database"); 
      storeUser(admin); 
      logger.info("schema creation complete"); 
      return; 
     } 
     logger.info("database schema exists, normal startup"); 
    } 
} 

的SchemaHelper.java:

public class SchemaHelper { 

    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    private String driverClassName; 
    private String url; 
    private String username; 
    private String password; 
    private String hibernateDialect; 
    private String dataSourceJndiName; 

    public void setDriverClassName(String driverClassName) { 
     this.driverClassName = driverClassName; 
    } 

    public void setHibernateDialect(String hibernateDialect) { 
     this.hibernateDialect = hibernateDialect; 
    } 

    public void setUrl(String url) { 
     this.url = url; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public void setDataSourceJndiName(String dataSourceJndiName) { 
     this.dataSourceJndiName = dataSourceJndiName; 
    } 

    /** 
    * create tables using the given Hibernate configuration 
    */ 
    public void createSchema() {   
     AnnotationConfiguration configuration = new AnnotationConfiguration(); 
     if (StringUtils.hasText("dataSourceJndiName")) { 
      configuration.setProperty("hibernate.connection.datasource", dataSourceJndiName); 
     } else { 
      configuration.setProperty("hibernate.connection.driver_class", driverClassName); 
      configuration.setProperty("hibernate.connection.url", url); 
      configuration.setProperty("hibernate.connection.username", username); 
      configuration.setProperty("hibernate.connection.password", password); 
     } 

     configuration.setProperty("hibernate.dialect", hibernateDialect); 
     configuration.addAnnotatedClass(User.class); 
     configuration.addAnnotatedClass(Role.class); 
     logger.info("begin database schema creation ========================="); 
     new SchemaUpdate(configuration).execute(true, true); 
     logger.info("end database schema creation ==========================="); 
    } 
} 

而且hibernate.cfg.xml:

<hibernate-configuration> 
<session-factory> 
    <mapping class="info.ems.models.User" /> 
    <mapping class="info.ems.models.Role" /> 
</session-factory> 
</hibernate-configuration> 

正如你可以看到HibernateEMSDao.java我试图找到预期的数据库架构是否存在,否则SchemaHelper.java数据库架构将被创建。但不幸的是,它不工作。我得到例外:

13:26:04,225 INFO [STDOUT] 2011-05-29 13:26:04,225 [ScannerThread] INFO [info.ems.datasource.DataSourceFactory] - Embedded HSQLDB mode detected, switching on spring single connection data source. 
13:26:05,063 INFO [STDOUT] 2011-05-29 13:26:05,063 [ScannerThread] WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: -22, SQLState: S0002 
13:26:05,063 INFO [STDOUT] 2011-05-29 13:26:05,063 [ScannerThread] ERROR [org.hibernate.util.JDBCExceptionReporter] - Table not found in statement [select user0_.USER_ID as USER1_0_, user0_.USERNAME as USERNAME0_, user0_.PASSWORD as PASSWORD0_, user0_.NAME as NAME0_, user0_.EMAIL as EMAIL0_, user0_.LOCKED as LOCKED0_ from USER user0_ where user0_.USER_ID=1] 
13:26:05,064 INFO [STDOUT] 2011-05-29 13:26:05,064 [ScannerThread] WARN [info.ems.hibernate.HibernateEMSDao] - expected database schema does not exist, will create. Error is: could not execute query; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query 
13:26:05,065 INFO [STDOUT] 2011-05-29 13:26:05,065 [ScannerThread] INFO [info.ems.hibernate.SchemaHelper] - begin database schema creation ========================= 
13:26:05,072 INFO [STDOUT] 2011-05-29 13:26:05,071 [ScannerThread] FATAL [org.hibernate.connection.DatasourceConnectionProvider] - Could not find datasource: 
java.lang.ClassCastException: org.jnp.interfaces.NamingContext cannot be cast to javax.sql.DataSource 

我做错了什么,任何信息将对我很有帮助。

感谢和问候。

回答

0

我认为(我可能是错的; D)异常说明发生了什么。

您定义:

<bean id="dataSource" class="info.ems.datasource.DataSourceFactory">

这是不是一个数据源之后,你把它传递到:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/>

所在类别蒙上发生。

+0

谢谢。但是,如果我使用hibernate映射文件而不是hibernate批注,并使用Configuration而不是AnnotationConfiguration,那么它不会产生问题。到目前为止,我认为AnnotationConfiguration需要hibernate.connection.datasource属性,它没有设置。我没有找到HSQLDB的hibernate.connection.datasource。我有的休眠属性:database.driver = org.hsqldb.jdbcDriver database.url = jdbc:hsqldb:file:$ {ems.home}/db/ems database.username = sa database.password = hibernate。 dialect = org.hibernate.dialect.HSQLDialect hibernate.show_sql = false – 2011-05-29 09:38:49