0
GORM OptimizationBurt BeckwithSpringSource                                                  CONFIDENTIAL                  ...
Agenda Mapping Database Views Writing a Custom Configuration Subclass for Fun and Profit Read-only Domain Classes Moni...
Also See Advanced GORM - Performance, Customization and Monitoring • Spring One / class UserInfo {                2GX 201...
Mapping Database Views         CONFIDENTIAL    4
Database View –> Entity    class Organization {      String name    }                                                class...
Database View –> Entity   CREATE OR REPLACE VIEW v_user_info AS   SELECT u.name, u.id, u.version, o.name org_name   FROM a...
Database View –> Entity ERROR hbm2ddl.SchemaExport  ­  Unsuccessful: create table v_user_info (id  bigint not null auto_in...
Database View –> EntityRegister a Custom Configuration in DataSource.groovy         dataSource {           pooled = true  ...
Database View –> Entity   public class DdlFilterConfiguration extends GrailsAnnotationConfiguration {       private static...
Database View –> Entity      grails-app/conf/hibernate/hibernate.cfg.xml    <hibernate­configuration>       <session­facto...
Database View –> Entity     grails-app/conf/hibernate/misc.mysql.innodb.hbm.xml    <hibernate­mapping>       <database­obj...
Subdomain Entity      “Subdomain” with a subset of AuthUser data:               class Person {                 String name...
Subdomain Entity      Updatable Subdomain:               class Person {                 String name                 Organi...
Writing a Custom Configuration Subclass for               Fun and Profit                   CONFIDENTIAL               14
Writing a Custom Configuration Subclass for Fun and ProfitCustom Configurations: http://burtbeckwith.com/blog/?p=465 Exam...
Writing a Custom Configuration Subclass for Fun and Profit secondPassCompile()  • Access each PersistentClass/RootClass a...
Read-only Domain Classes          CONFIDENTIAL     17
Read-only Domain Classes Not 100% possible, but close enough Hibernate • Seems possible via setMutable(false) in a custo...
Read-only Domain Classes Grails • Only beforeUpdate supports vetoing by returning false • A hackish solution would be to ...
Read-only Domain Classes      grails-app/conf/spring/resources.groovy    import gr8conf.ReadOnlyEventListener    import o....
Read-only Domain Classes   src/groovy/gr8conf/ReadOnlyEventListener.groovy   class ReadOnlyEventListener implements PreDel...
Read-only Domain Classes   grails-app/domain/gr8conf/LegacyData.groovy                class LegacyData {                  ...
Read-only Domain Classes ReadOnlyEventListener • delete()   • silently fails • Update with save()   • silently fails • Ne...
Read-only Domain Classes   You can also map a second writable domain class   to the same table, e.g. for admin:   class Us...
Monitoring   CONFIDENTIAL   25
Monitoring SQL logging • logSql=true in DataSource.groovy • org.hibernate.SQL → debug, org.hibernate.type → trace     app...
Monitoring Spring Insight lets you drill down to SQL and view timing • http://www.grails.org/screencast/show/13 Profiler...
Questions?   CONFIDENTIAL   28
Upcoming SlideShare
Loading in...5
×

GR8Conf 2011: GORM Optimization

2,836

Published on

Published in: Business, Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,836
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
66
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Transcript of "GR8Conf 2011: GORM Optimization"

  1. 1. GORM OptimizationBurt BeckwithSpringSource CONFIDENTIAL © 2010 SpringSource, A division of VMware. All rights reserved
  2. 2. Agenda Mapping Database Views Writing a Custom Configuration Subclass for Fun and Profit Read-only Domain Classes Monitoring CONFIDENTIAL 2
  3. 3. Also See Advanced GORM - Performance, Customization and Monitoring • Spring One / class UserInfo { 2GX 2010 String name String orgName • http://www.infoq.com/presentations/GORM-Performance static mapping = { • Primarily focused on v_user_info table performance implications around } } using Many-to-One and Many-to-Many in GORM CONFIDENTIAL 3
  4. 4. Mapping Database Views CONFIDENTIAL 4
  5. 5. Database View –> Entity class Organization { String name } class UserInfo { String name String orgName } class AuthUser { String name String password Organization organization } CONFIDENTIAL 5
  6. 6. Database View –> Entity CREATE OR REPLACE VIEW v_user_info AS SELECT u.name, u.id, u.version, o.name org_name FROM auth_user u, organization o WHERE u.organization_id = o.id class UserInfo { String name String orgName static mapping = { table v_user_info } } CONFIDENTIAL 6
  7. 7. Database View –> Entity ERROR hbm2ddl.SchemaExport  ­  Unsuccessful: create table v_user_info (id  bigint not null auto_increment, version  bigint not null, name varchar(255) not  null, org_name varchar(255) not null,  primary key (id)) type=InnoDB ERROR hbm2ddl.SchemaExport  ­ Table  v_user_info already exists CONFIDENTIAL 7
  8. 8. Database View –> EntityRegister a Custom Configuration in DataSource.groovy dataSource { pooled = true driverClassName = ... username = ... password = ... dialect = ... configClass = gr8conf.DdlFilterConfiguration } CONFIDENTIAL 8
  9. 9. Database View –> Entity public class DdlFilterConfiguration extends GrailsAnnotationConfiguration { private static final String[] IGNORED_NAMES = { "v_user_info" }; ... private boolean isIgnored(String command) { command = command.toLowerCase(); for (String table : IGNORED_NAMES) { if (command.startsWith("create table " + table + " ") || command.startsWith("alter table " + table + " ") || command.startsWith("drop table " + table) || command.startsWith("drop table if exists " + table)) { return true; } } return false; } } CONFIDENTIAL 9
  10. 10. Database View –> Entity grails-app/conf/hibernate/hibernate.cfg.xml <hibernate­configuration>    <session­factory>       <mapping resource=misc.mysql.innodb.hbm.xml/>       <mapping resource=misc.h2.hbm.xml/>    </session­factory> </hibernate­configuration> CONFIDENTIAL 10
  11. 11. Database View –> Entity grails-app/conf/hibernate/misc.mysql.innodb.hbm.xml <hibernate­mapping>    <database­object>       <create>          CREATE OR REPLACE VIEW v_user_info AS          SELECT u.name, u.id, u.version, o.name org_name          FROM auth_user u, organization o          WHERE u.organization_id = o.id       </create>       <drop>DROP VIEW IF EXISTS v_user_info</drop>       <dialect­scope           name=org.hibernate.dialect.MySQLInnoDBDialect />    </database­object> </hibernate­mapping> CONFIDENTIAL 11
  12. 12. Subdomain Entity “Subdomain” with a subset of AuthUser data: class Person { String name Organization organization static mapping = { table auth_user } } CONFIDENTIAL 12
  13. 13. Subdomain Entity Updatable Subdomain: class Person { String name Organization organization static mapping = { table auth_user dynamicUpdate true } } CONFIDENTIAL 13
  14. 14. Writing a Custom Configuration Subclass for Fun and Profit CONFIDENTIAL 14
  15. 15. Writing a Custom Configuration Subclass for Fun and ProfitCustom Configurations: http://burtbeckwith.com/blog/?p=465 Examples • Previous SQL generation example • Overrides generateSchemaCreationScript(), generateDropSchemaScript(), and generateSchemaUpdateScript() • Specifying the connection.provider_class property • Overrides buildSettings() • Renaming columns of a composite foreign key • Overrides secondPassCompile() • Overriding the EntityPersister class • Overrides secondPassCompile() • Using field access • Overrides secondPassCompile() CONFIDENTIAL 15
  16. 16. Writing a Custom Configuration Subclass for Fun and Profit secondPassCompile() • Access each PersistentClass/RootClass and call any of • addFilter() • setDynamicUpdate() • setBatchSize() • setExplicitPolymorphism() • setCustomSQLDelete() • setOptimisticLockMode() • setCustomSQLInsert() • setSelectBeforeUpdate() • setCustomSQLUpdate() • setWhere() • setDynamicInsert() CONFIDENTIAL 16
  17. 17. Read-only Domain Classes CONFIDENTIAL 17
  18. 18. Read-only Domain Classes Not 100% possible, but close enough Hibernate • Seems possible via setMutable(false) in a custom Configuration, but: • Wont block saves or deletes, only disables dirty-check updates • Does nothing with collections since theyre a PersistentSet or PersistentList and managed separately (but you wouldnt want to map collections anyway, right?) • See http://docs.jboss.org/hibernate/core/3.5/reference/en/html/readonly.html CONFIDENTIAL 18
  19. 19. Read-only Domain Classes Grails • Only beforeUpdate supports vetoing by returning false • A hackish solution would be to throw an exception in beforeDelete and beforeInsert • Better solution: hibernateEventListeners bean in grails­ app/conf/spring/resources.groovy • Still a good idea to use a custom Configuration and call setMutable(false) to reduce memory usage CONFIDENTIAL 19
  20. 20. Read-only Domain Classes grails-app/conf/spring/resources.groovy import gr8conf.ReadOnlyEventListener import o.c.g.g.orm.hibernate.HibernateEventListeners beans = {    readOnlyEventListener(ReadOnlyEventListener)    hibernateEventListeners(HibernateEventListeners) {       listenerMap = [pre­delete: readOnlyEventListener,                      pre­insert: readOnlyEventListener,                      pre­update: readOnlyEventListener]    } } CONFIDENTIAL 20
  21. 21. Read-only Domain Classes src/groovy/gr8conf/ReadOnlyEventListener.groovy class ReadOnlyEventListener implements PreDeleteEventListener,          PreInsertEventListener, PreUpdateEventListener {  private static final List<String> READ_ONLY = [gr8conf.LegacyData]  boolean onPreDelete(PreDeleteEvent event) {     isReadOnly event.persister.entityName  }  boolean onPreInsert(PreInsertEvent event) {     isReadOnly event.persister.entityName  }  boolean onPreUpdate(PreUpdateEvent event) {     isReadOnly event.persister.entityName  }  private boolean isReadOnly(String name) { READ_ONLY.contains name } } CONFIDENTIAL 21
  22. 22. Read-only Domain Classes grails-app/domain/gr8conf/LegacyData.groovy class LegacyData {    String name    static mapping = {       id column: legacy_data_id       version false    } } CONFIDENTIAL 22
  23. 23. Read-only Domain Classes ReadOnlyEventListener • delete() • silently fails • Update with save() • silently fails • New instance save() • Throws exception ? CONFIDENTIAL 23
  24. 24. Read-only Domain Classes You can also map a second writable domain class to the same table, e.g. for admin: class User { class WritableUser {    String username    String username    String password    String password }    static mapping = {       table user    } } CONFIDENTIAL 24
  25. 25. Monitoring CONFIDENTIAL 25
  26. 26. Monitoring SQL logging • logSql=true in DataSource.groovy • org.hibernate.SQL → debug, org.hibernate.type → trace appenders {    file name: sql, file: sql.log } debug additivity: false, sql: org.hibernate.SQL trace additivity: false, sql: org.hibernate.type • P6spy plugin • Use SQL Profiler Swing app to view realtime logs; see Mike Hugos blog post Grails, p6spy and Sql Profiler • Run explain (Oracle, MySQL, others) on real queries to look for missing indexes CONFIDENTIAL 26
  27. 27. Monitoring Spring Insight lets you drill down to SQL and view timing • http://www.grails.org/screencast/show/13 Profiler plugin can give you timing data JavaMelody Plugin App Info plugin CONFIDENTIAL 27
  28. 28. Questions? CONFIDENTIAL 28
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×