vladmihalcea / hypersistence-optimizer

Hypersistence Optimizer allows you to get the most out of JPA and Hibernate. By scanning your application configuration and mappings, Hypersistence Optimizer can tell you what changes you need to do to speed up your data access layer.
https://vladmihalcea.com/hypersistence-optimizer/
Apache License 2.0
306 stars 43 forks source link

initial commit for grails 2.5.6 example #207

Closed pgutierrezn2 closed 1 year ago

vladmihalcea commented 1 year ago

Thanks, I'll review it when I have some time.

vladmihalcea commented 1 year ago

I tried to run it, but it fails with:

>grailsw
Error opening zip file or JAR manifest missing : wrapper/springloaded-1.2.7.RELEASE.jar
Error occurred during initialization of VM
agent library failed to init: instrument
vladmihalcea commented 1 year ago

I created this GitHub repository for Grails and Hibernate 4.

vladmihalcea commented 1 year ago

@pgutierrezn2 So, this repository shows how Hypersistence Optimizer works on this Grails app with Hibernate 4.3.

If you run the application, it will generate the following events:

ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Visit] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Pet] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - BidirectionalSynchronizationEvent - The [visits] bidirectional association in the [org.grails.samples.Pet] entity requires both ends to be synchronized. Consider adding the [addVisit(org.grails.samples.Visit visit)] and [removeVisit(org.grails.samples.Visit visit)] synchronization methods. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#BidirectionalSynchronizationEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Owner] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - BidirectionalSynchronizationEvent - The [pets] bidirectional association in the [org.grails.samples.Owner] entity requires both ends to be synchronized. Consider adding the [addPet(org.grails.samples.Pet pet)] and [removePet(org.grails.samples.Pet pet)] synchronization methods. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#BidirectionalSynchronizationEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Person] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Vet] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.PetType] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - IdentityGeneratorEvent - The [id] identifier attribute in the [org.grails.samples.Speciality] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Consider using the SEQUENCE identifier strategy instead. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent
ERROR Hypersistence Optimizer - CRITICAL - JdbcBatchSizeEvent - If you set the [hibernate.jdbc.batch_size] configuration property to a value greater than 1 (usually between 5 and 30), Hibernate can then execute SQL statements in batches, therefore reducing the number of database network roundtrips. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#JdbcBatchSizeEvent
ERROR Hypersistence Optimizer - CRITICAL - JdbcFetchSizeEvent - If you set the [hibernate.jdbc.fetch_size] configuration property to a value greater than the current value of [100], then Hibernate will use fewer database network roundtrips to fetch a JDBC ResultSet and transform it to a List of entities, DTOs or scalar types. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#JdbcFetchSizeEvent
ERROR Hypersistence Optimizer - BLOCKER - SchemaGenerationEvent - You should not set the [hibernate.hbm2ddl.auto] configuration property to the value of [create-drop], as Hibernate will then manage the database schema for you. Instead, you should use an incremental schema migration tool (e.g., Flyway, Liquibase), which allows you to use any database-specific DDL construct. By storing the migration scripts in the Version Control System along with the application source code, you will always remember why a certain schema change was done. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#SchemaGenerationEvent
ERROR Hypersistence Optimizer - BLOCKER - PooledSequenceOptimizerEvent - You should set the [hibernate.id.new_generator_mappings] configuration property to the value of [true], as Hibernate can then use the pooled or pooled-lo identifier optimizers for sequence-based entity identifiers. Note that the pooled and pooled-lo optimizers are not backward compatible with the legacy hilo optimizer that you might have used with Hibernate ORM 3 or 4. So, if you were using the hilo optimizer, then you would need to increase the current sequence number so that is greater than any previously allocated entity identifiers. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#PooledSequenceOptimizerEvent
ERROR Hypersistence Optimizer - CRITICAL - DefaultQueryPlanCacheMaxSizeEvent - You should set the [hibernate.query.plan_cache_max_size] configuration property to a value that allows you to hold all JPQL, Criteria API, or SQL queries executed with Hibernate. The default query plan cache size is [2048] and might not be enough for a non-trivial application. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#DefaultQueryPlanCacheMaxSizeEvent
pgutierrezn2 commented 1 year ago

Please, correct me if I'm wrong, but isn't the RuntimeScanner disabled in this example?

vladmihalcea commented 1 year ago

The Runtime scanner is enabled by default, so unless explicitly disabled, it should be active when you bootstrap the application.

pgutierrezn2 commented 1 year ago

Ok, it is enabled by default, but then, none of the Runtime events has been identified as critical/blocker in this example, right?

However, with the current configuration (I understand the sessionFactory provided by Grails is not being decorated), it is still able to generate Runtime events?

vladmihalcea commented 1 year ago

@pgutierrezn2 I tried to decorate the SessionFactory:

sessionFactory(HypersistenceConfigurableLocalSessionFactoryBean) {
    dataSource = ref('dataSource')
    hibernateProperties = ref('hibernateProperties')
    grailsApplication = ref('grailsApplication')
}

But it looks like Grails uses some hard-coded SessionFactoryImpl castings:

ConnectionProvider connectionProvider = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(ConnectionProvider.class);

So, only the Configuration and Mapping scanners will work.

pgutierrezn2 commented 1 year ago

Now I understand. Thanks for your effort It's been a pleasure

vladmihalcea commented 1 year ago

You're welcome. The good news is that you can still detect a lot of issues with mapping and configs even on older Grails apps.

pgutierrezn2 commented 1 year ago

Sure, we'll buy one to test it further. Thanks

vladmihalcea commented 1 year ago

Enjoy using it. Hopefully, newer Grails versions use the Hibernate interfsces, like SessionFactory, instead of casting to implementation classes that are now in the internal packages.