本文不详细描述整合的过程,我把可以运行的代码提交到github,后面代码的地址。

什么是JavaConfig

JavaConfig就是使用注释来描述Spring Bean配置的组件。Spring使用注释来描述Bean的配置与采用XML相比,因类注释是在一个类源代码中,可以获得类型安全检查的好处。可以良好的支持重构。Spring的spring-boot子项目有对JavaConfig的深入支持,官方文档以入门基础为主,深入的文档较少,深入研究需要看源码,作为年轻的项目,还有很长的路要走。[2014-07]

例子SHD201407-app

1 基于maven的项目,整合内容spring4.0.3+hibernate4.3.5+jpa2.1+druid1.0.6+JDK8编写 2 Spring的JavaConfig编写代码。 3 使用Druid连接池管理数据库连接,druid1.0.6提供的DruidConnectionProvider不适用Hibernate4.3,抛出下面的异常:

  1. Caused by: java.lang.ClassNotFoundException: org.hibernate.service.jdbc.connections.spi.ConnectionProvider
  2. at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
  3. at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
  4. at java.security.AccessController.doPrivileged(Native Method)
  5. at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
  6. at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
  7. at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
  8. at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
  9. ... 65 more

在项目中,参考原有实现com.urely.shd2014.DruidConnectionProvider,就可以继续使用。 对JavaConfig整合感兴趣的同学,可以通过下面地址下载源码学习:https://github.com/guocw998/SHD201407-app

factory.afterPropertiesSet()切入点

  1. @Bean
  2. public EntityManagerFactory entityManagerFactory() throws SQLException {
  3.     HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
  4.  
  5. // vendorAdapter.setGenerateDdl(true);

  6.     LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
  7.  
  8. // factory.setJpaProperties(jpaProperties);

  9. factory.setJpaVendorAdapter(vendorAdapter);

  10. factory.setPackagesToScan("com.urely.shd2014.entity");

  11. // factory.setDataSource(dataSource());

  12. logger.info("Before LocalContainerEntityManagerFactoryBean.afterPropertiesSet():::"+factory.getJpaPropertyMap());

  13. factory.afterPropertiesSet();

  14. logger.info("After LocalContainerEntityManagerFactoryBean.afterPropertiesSet():::"+factory.getJpaPropertyMap());

  15.     return factory.getObject();
  16. }
  17.  

大家在研究过程中,都会和我一样有疑问:我们hibernate配置属性和Druid配置属性是如何正确加载到Spring容器?Spring容器如何正确的初始化数据源DataSource的?Spring的JavaConfig编程过程,Spring容器加载hibernate.properties配置,就能根据配置去初始化数据源DataSource和相应的数据数据处理层的初始化——这些神奇的过程都发生在factory.afterPropertiesSet()中。

hibernate.properties

  1. ##############################################################
  2. # spring+hibernate+jpa整合到时候,javaconfig的方式避免了XML,配置文件会自动加载到Hibernate的环境中:Environment
  3. # 在Properties p = org.hibernate.cfg.Environment.getProperties()中有所有hibernate.properties的属性。
  4. #
  5. # 把Druid配置整合到这里声明
  6. #
  7. ##############################################################
  8. #####################################################################################

  9. ###采用Druid连接池,下面的吉祥hibernate配置使用Druid的。

  10. #hibernate.connection.url=jdbc:mysql://localhost:3306/superweb?useUnicode=true&characterEncoding=utf-8

  11. #hibernate.connection.driver_class=com.mysql.jdbc.Driver

  12. #hibernate.connection.username=root

  13. #hibernate.connection.password=

  14. #c3p0

  15. #hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider

  16. #####################################################################################

  17. #####################################################################################

  18. #####保留的hiber配置

  19. #MYSQL

  20. hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

  21. #设置外连接抓取树的最大深度

  22. hibernate.max_fetch_depth=3

  23. #设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

  24. hibernate.jdbc.fetch_size=50

  25. hibernate.jdbc.batch_size=50

  26. #自动建表类型 validate|create|create-drop|update

  27. hibernate.hbm2ddl.auto=create-drop

  28. #是否显示SQL

  29. hibernate.show_sql=true

  30. #显示SQL是否格式化

  31. hibernate.format_sql=true

  32. #关闭二级缓存

  33. hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider

  34. #####################################################################################

  35. #####################################################################################

  36. #Druid配置

  37. #Druid::注意这里配置的ConnectionProvider!!! 第一次,配置错误了导致直接加不成功的异常!!

  38. #hibernate.connection.provider_class=com.alibaba.druid.support.hibernate.DruidConnectionProvider

  39. hibernate.connection.provider_class=com.urely.shd2014.DruidConnectionProvider

  40. 基本属性 urluserpassword

  41. url=jdbc:mysql://localhost:3306/superweb?useUnicode=true&characterEncoding=utf-8

  42. username=root

  43. password=

  44. ##数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass

  45. driverClassName=com.mysql.jdbc.Driver

  46. ###pool settings

  47. initialSize=0

  48. maxActive=20

  49. ###已经不再使用,配置了也没效果

  50. ##maxIdle=20

  51. ##最小连接池数量

  52. minIdle=3

  53. ##获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

  54. maxWait=60000

  55. ##是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。

  56. poolPreparedStatements=false

  57. ##要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

  58. maxOpenPreparedStatements=-1

  59. #用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。

  60. validationQuery=SELECT 'x'

  61. testOnBorrow=false

  62. testOnReturn=false

  63. testWhileIdle=true

  64. ##有两个含义:1) Destroy线程会检测连接的间隔时间, 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明

  65. timeBetweenEvictionRunsMillis=60000

  66. ##不再使用,一个DruidDataSource只支持一个EvictionRun

  67. #numTestsPerEvictionRun

  68. #minEvictableIdleTimeMillis

  69. #connectionInitSqls

  70. #exceptionSorter

  71. filters=stat

  72. #proxyFilters

  73. ###Druid::作者建议::在上面的配置中,通常你需要配置url、username、password,maxActive这四项。

  74. #####################################################################################