基于hibernate注释类创建数据库模式

时间:2011-05-29 08:31:18

标签: java hibernate spring

我有两个持久化类:User.java,Role.java,这些在hibernate.cfg.xml中声明。我在用春天。 applicationContext.xml具有:

<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

我正在以错误的方式做事,任何信息对我都非常有帮助。

谢谢和问候。

1 个答案:

答案 0 :(得分:0)

我认为(我可能错了; D)该例外确切地说明了发生了什么。

您定义:

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

哪个不是数据源,然后将其传递给:

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

班级演员的地方。