情感視頻素材網(wǎng)站劉連康seo培訓(xùn)哪家強(qiáng)
? ? ? ? ? ? ? ? ? ??
?Jpa與Druid線程池及Spring Boot整合(一)
Jpa與Druid線程池及Spring Boot整合(二):幾個(gè)坑
附錄官網(wǎng)文檔:core.domain-events域事件
從聚合根發(fā)布事件
存儲(chǔ)庫(kù)管理的實(shí)體是聚合根。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)應(yīng)用程序中,這些聚合根通常會(huì)發(fā)布領(lǐng)域事件。Spring Data 提供了一個(gè)名為 的注釋@DomainEvents
,您可以在聚合根的方法上使用該注釋,以使該發(fā)布盡可能簡(jiǎn)單,如以下示例所示:
class AnAggregateRoot {@DomainEvents (1)Collection<Object> domainEvents() {// … return events you want to get published here}@AfterDomainEventPublication (2)void callbackMethod() {// … potentially clean up domain events list}
}
使用的方法@DomainEvents 可以返回單個(gè)事件實(shí)例或事件集合。它不能接受任何參數(shù)。 | |
發(fā)布所有事件后,我們有一個(gè)用 注釋的方法@AfterDomainEventPublication 。您可以使用它來(lái)潛在地清理要發(fā)布的事件列表(以及其他用途)。 |
每次調(diào)用以下 Spring 數(shù)據(jù)存儲(chǔ)庫(kù)方法之一時(shí)都會(huì)調(diào)用這些方法:
-
save(…)
,saveAll(…)
-
delete(…)
,?deleteAll(…)
,?deleteAllInBatch(…)
,deleteInBatch(…)
請(qǐng)注意,這些方法將聚合根實(shí)例作為參數(shù)。這就是為什么deleteById(…)
明顯不存在的原因,因?yàn)閷?shí)現(xiàn)可能會(huì)選擇發(fā)出刪除實(shí)例的查詢,因此我們首先永遠(yuǎn)無(wú)法訪問(wèn)聚合實(shí)例。
在使用Spring Boot JPA時(shí),open-in-view 選項(xiàng)默認(rèn)為true。啟動(dòng)時(shí)在日志中會(huì)出現(xiàn)警告。?
一坑:druid與jpa整合,啟動(dòng)出現(xiàn)如下警告:
JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
?處理方案:
按照日志要求將 open-in-view=false。再次啟動(dòng),如果在實(shí)體類中外鍵字段使用了懶加載模式,在視圖層中調(diào)用數(shù)據(jù)時(shí),則會(huì)出現(xiàn) no session 異常。
解決方法:手動(dòng)注冊(cè)O(shè)penEntityManagerInViewFilter過(guò)濾器,改變session的生命周期,當(dāng)web請(qǐng)求關(guān)閉時(shí)才結(jié)束session。
?
? javaConfig注入bean
@Bean public FilterRegistrationBean<OpenEntityManagerInViewFilter> registerOpenEntityManagerInViewFilterBean() {FilterRegistrationBean<OpenEntityManagerInViewFilter> registrationBean = new FilterRegistrationBean<>();OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter();registrationBean.setFilter(filter);registrationBean.setOrder(5);return registrationBean; }
解疑:
如果使用的是 JPA 則對(duì)應(yīng)OpenEntityManagerInViewFilter,Hibernate對(duì)應(yīng)OpenSessionInViewFilter
疑問(wèn):registrationBean.setOrder(5),order為什么是5
OpenSessionInViewInterceptor&OpenSessionInViewFilter,OpenEntityManagerInViewInterceptor&OpenEntityManagerInViewFilter這幾個(gè)類的區(qū)別以及使的的場(chǎng)景
?
重新啟動(dòng): 正常:
二坑:? ?springboot整合JPA出現(xiàn)異常java.lang.IllegalArgumentException: Not a managed type: class xx
方案: 一
啟動(dòng)類或者JavaConfig添加添加掃描實(shí)體的路徑: @EntityScan(basePackages = "org.jd.websocket.auth.data.reactor.jpa") @EnableTransactionManagement // 開啟事務(wù)的支持 @EnableJpaRepositories(basePackages = {"org.jd.websocket.auth.data.reactor.repository","org.jd.websocket.auth.data.reactor.jpa"},includeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*CrudRepository")},excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*SomeOtherRepository")})
?方案: 二
@Configuration? ? ?javaConfig中注入Bean
@Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);// entity掃描的包路徑factory.setPackagesToScan("org.jd.websocket.auth.data.reactor.jpa");factory.setDataSource(dataSource());return factory; }
@Value("${spring.datasource.url}") private String dbUrl;@Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driverClassName;@Value("${spring.datasource.initialSize}") private int initialSize; @Value("${spring.datasource.minIdle}") private int minIdle; @Value("${spring.datasource.maxActive}") private int maxActive; @Value("${spring.datasource.maxWait}") private int maxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis}") private int minEvictableIdleTimeMillis; @Value("${spring.datasource.validationQuery}") private String validationQuery; @Value("${spring.datasource.testWhileIdle}") private boolean testWhileIdle; @Value("${spring.datasource.testOnBorrow}") private boolean testOnBorrow; @Value("${spring.datasource.testOnReturn}") private boolean testOnReturn; @Value("${spring.datasource.poolPreparedStatements}") private boolean poolPreparedStatements; @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") private int maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.filters}") private String filters; @Value("{spring.datasource.connectionProperties}") private String connectionProperties;@Bean @Primary public DataSource dataSource() {DruidDataSource datasource = new DruidDataSource();datasource.setUrl(dbUrl);datasource.setUsername(username);datasource.setPassword(password);datasource.setDriverClassName(driverClassName);// configurationdatasource.setInitialSize(initialSize);datasource.setMinIdle(minIdle);datasource.setMaxActive(maxActive);datasource.setMaxWait(maxWait);datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);datasource.setValidationQuery(validationQuery);datasource.setTestWhileIdle(testWhileIdle);datasource.setTestOnBorrow(testOnBorrow);datasource.setTestOnReturn(testOnReturn);datasource.setPoolPreparedStatements(poolPreparedStatements);datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);try {datasource.setFilters(filters);} catch (SQLException e) {System.err.println("druid configuration initialization filter: " + e);}datasource.setConnectionProperties(connectionProperties);return datasource; }@Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);// entity掃描的包路徑factory.setPackagesToScan("org.jd.websocket.auth.data.reactor.jpa");factory.setDataSource(dataSource());return factory; }
坑三:? ? 多數(shù)據(jù)源注入,事務(wù)失效|解決方案;
* @Transactiona在多數(shù)據(jù)源下失效 * 在多數(shù)據(jù)源的情況下,如果transactionManager進(jìn)行了分開配置,比如這里針對(duì)三個(gè)數(shù)據(jù)源配置了三個(gè)transactionManager * =========================================================================================================== * @Bean("formTransactionManager") * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) { * return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject())); * } *============================================================================================================= * @Bean("fileTransactionManager") * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) { * return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject())); * } * ============================================================================================================ * @Primary * @Bean("userTransactionManager") * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) { * return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject())); * } * ============================================================================================================= * * 那么在使用@Transactional的時(shí)候需要指定transactionManager * @Transactional("formTransactionManager")
@EnableTransactionManagement // 開啟事務(wù)的支持
可以訪問(wèn)下druid監(jiān)控相關(guān)數(shù)據(jù):
http://localhost:9999/druid/
輸入上面的賬號(hào)和密碼:? 可以查看不同的選項(xiàng)卡,能幫助我們排查一些數(shù)據(jù)庫(kù)相關(guān)問(wèn)題