问题
It seems that org.hibernate.cfg.Configuration object can be used to perform validation programmatically, by calling the validateSchema method. However, this method needs dialect and databaseMetadata objects. I am using Spring and I can get a hold of AnnotationSessionFactoryBean object from spring context. So far I have the following code:
AnnotationSessionFactoryBean factory = null;
factory = (AnnotationSessionFactoryBean) context.getBean("AnnotationSessionFactory");
Configuration configuration = factory.getConfiguration();
//the following line does not work, ConnectionHelper hierarchy is not visible outside the package
ConnectionHelper connectionHelper =
new ManagedConnectionProviderConnectionHelper(factory.getHibernateProperties());
Dialect dialect = Dialect.getDialect(factory.getHibernateProperties());
Connection connection = null;
DatabaseMetadata databaseMetadata = null;
try {
databaseMetadata = new DatabaseMetadata(connection, dialect);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
configuration.validateSchema(dialect, databaseMetadata);
Am I on the right track? ConnectionHelper hierarchy is not visible out of the package so I can’t obtain the connection object that way, in order to construct databaseMetadata. How can I implement this?
EDIT: I think I have made some progress. There is a SchemaValidator class. The code now looks like this:
AnnotationSessionFactoryBean factory = context.getBean("&AnnotationSessionFactory");
Configuration configuration = factory.getConfiguration();
SchemaValidator validator = new SchemaValidator(configuration);
validator.validate();
Howerver, now I am getting the following error:
org.hibernate.HibernateException: No local DataSource found for configuration - 'dataSource' property must be set on LocalSessionFactoryBean
回答1:
In the end, when using Spring this is not that simple. I managed to do it extending the AnnotationSessionFactoryBean like this:
public class SchemaValidatingAnnotationSessionFactoryBean extends
AnnotationSessionFactoryBean {
public void validateDatabaseSchema() throws DataAccessException {
logger.info("Validating database schema for Hibernate SessionFactory");
HibernateTemplate hibernateTemplate = new HibernateTemplate(
getSessionFactory());
hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER);
hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Connection con = session.connection();
Dialect dialect = Dialect.getDialect(getConfiguration()
.getProperties());
DatabaseMetadata metadata = new DatabaseMetadata(con, dialect);
Configuration configuration = getConfiguration();
configuration.validateSchema(dialect, metadata);
return null;
}
});
}
}
回答2:
I have found a simpler solution for invoking hibernate mapping validation that works for me : LocalSessionFactoryBean.validateDatabaseSchema() (which effectively does the same thing as the code in Dan's answer above)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/some-test-context.xml" })
public class TestMapping {
@Autowired
ApplicationContext context;
@Test
public void validateSchema() {
AnnotationSessionFactoryBean factory = (AnnotationSessionFactoryBean)context
.getBean("&mySessionFactory");
factory.validateDatabaseSchema();
}
}
来源:https://stackoverflow.com/questions/2327423/how-to-validate-database-schema-programmatically-in-hibernate-with-annotations