Reputation: 3056
How to truncate all table data using hibernate configuration?
For example hibernate.hbm2ddl.auto=validate
will check validity of entity model in database. Now I need an option to truncate all tables during startup of an application.
Upvotes: 2
Views: 6330
Reputation: 9158
It seems that Integrator interface is changed. I re-wrote the answer for the new interface:
static final class TruncatorIntegrator implements org.hibernate.integrator.spi.Integrator {
@Override
public void integrate(Metadata metadata,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
try (Session session = sessionFactory.openSession()) {
session.doWork(connection -> {
try (PreparedStatement preparedStatement = connection.prepareStatement("SET FOREIGN_KEY_CHECKS = 0;")) {
preparedStatement.executeUpdate();
System.out.printf("Disabled foreign key checks%n");
} catch (SQLException e) {
System.err.printf("Cannot disable foreign key checks: %s: %s%n", e, e.getCause());
}
metadata.collectTableMappings().forEach(table -> {
String tableName = table.getQuotedName();
try (PreparedStatement preparedStatement = connection.prepareStatement("TRUNCATE TABLE " + tableName)) {
preparedStatement.executeUpdate();
System.out.printf("Truncated table: %s%n", tableName);
} catch (SQLException e) {
System.err.printf("Couldn't truncate table %s: %s: %s%n", tableName, e, e.getCause());
}
});
try (PreparedStatement preparedStatement = connection.prepareStatement("SET FOREIGN_KEY_CHECKS = 1;")) {
preparedStatement.executeUpdate();
System.out.printf("Enabled foreign key checks%n");
} catch (SQLException e) {
System.err.printf("Cannot enable foreign key checks: %s: %s%n", e, e.getCause());
}
});
}
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
}
}
Usage:
BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().applyIntegrator(new TruncatorIntegrator()).build();
StandardServiceRegistry registry = new StandardServiceRegistryBuilder(bootstrapServiceRegistry).build();
SessionFactory sessionFactory = new Configuration().buildSessionFactory(registry);
Upvotes: 3
Reputation: 9022
Hibernate does only have the possibility to recreate the schema using hibernate.hbm2ddl.auto=create
or hibernate.hbm2ddl.auto=create-drop
Another option is to create an import.sql
in the root of your classpath that contains the desired TRUNCATE
statements. That file is executed automatically on startup (after validation). In that case you will have to keep the table names in sync with your database.
The last possible solution is to have your own "truncate implementation" at startup, for example as Integrator
:
public class Truncator implements Integrator {
public void integrate(final Configuration config,
final SessionFactoryImplementor sessionFactory,
final SessionFactoryServiceRegistry sessionFactoryServiceRegistry) {
// Create session
Session session = sessionFactory.openSession();
try {
// Find all involved tables
for (final ClassMetadata metadata : sessionFactory.getAllClassMetadata().values()) {
final String tableName = ((AbstractEntityPersister) metadata).getTableName();
if (tableName != null) {
session.createSQLQuery("TRUNCATE TABLE " + tableName).executeUpdate();
}
}
final Map<String, CollectionMetadata> allCollectionMetadata = sessionFactory.getAllCollectionMetadata();
for (final CollectionMetadata metadata : allCollectionMetadata.values()) {
final String tableName = ((AbstractCollectionPersister) metadata).getTableName();
if (tableName != null) {
session.createSQLQuery("TRUNCATE TABLE " + tableName).executeUpdate();
}
}
} finally {
session.close();
}
}
}
An Integrator
has to be declared in META-INF/services/org.hibernate.integrator.spi.Integrator
, which just contains the full qualified class name.
If you use enhanced features (like Envers), you will need to find more table names - so this is more a proof of concept for simple data models.
Upvotes: 3