日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离

發(fā)布時間:2025/3/15 javascript 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

相關(guān)代碼:github OSCchina

JPA是什么

JPA(Java Persistence API)是Sun官方提出的Java持久化規(guī)范,它為Java開發(fā)人員提供了一種對象/關(guān)聯(lián)映射工具 來管理Java應(yīng)用中的關(guān)系數(shù)據(jù).它包括以下幾方面的內(nèi)容:

  • 1.ORM映射 支持xml和注解方式建立實體與表之間的映射.
  • 2.Java持久化API 定義了一些常用的CRUD接口,我們只需直接調(diào)用,而不需要考慮底層JDBC和SQL的細節(jié).
  • 3.JPQL查詢語言 這是持久化操作中很重要的一個方面,通過面向?qū)ο蠖敲嫦驍?shù)據(jù)庫的查詢語言查詢數(shù)據(jù),避免程序的SQL語句緊密耦合.
    在工作中,我們都會用到ORM技術(shù),比如Hibernate,JOOQ等,根據(jù)需求的不同,我們會采用不同的ORM框架,當(dāng)我們需要 更換ORM框架來滿足我們的需求時,由于不同ORM框架的實現(xiàn),使用方式的區(qū)別以及各自為營,我們往往需要對代碼進行重構(gòu).JPA的 出現(xiàn)就是為了解決這個問題,JPA充分吸收了現(xiàn)有一些ORM框架的優(yōu)點,具有易于使用,伸縮性強等優(yōu)點,為ORM技術(shù)提供了一套標(biāo)準(zhǔn)的 接口用來整合不同的ORM框架.

Hibernate對JPA的實現(xiàn)

JPA本身并不做具體的實現(xiàn),而只是定義了一些接口規(guī)范,讓其它ORM來具體的實現(xiàn)這些接口,就目前來說,對JPA規(guī)范實現(xiàn)最好的就是 Hibernate了.這里提一下Mybatis,Mybatis并沒有實現(xiàn)JPA規(guī)范,它本身也不能算做一個真正的ORM框架.

Spring Data JPA是什么

Spring Data JPA只是Spring Data框架的一個模塊,可以極大的簡化JPA的使用,Spring Data JPA強大的地方還在于能夠簡化我們 對持久層業(yè)務(wù)邏輯的開發(fā),通過規(guī)范持久層方法的名稱,通過名稱來判斷需要實現(xiàn)什么業(yè)務(wù)邏輯,我們機會可以在不寫一句sql,不做任何dao層 邏輯的情況下完成我們絕大部分的開發(fā),當(dāng)然,對于一些復(fù)雜的,性能要求高的查詢,Spring Data JPA一樣支持我們使用原生的sql.

在這里我們不過多的去介紹JPA以及Spring Data JPA,主要還是與SpringBoot集成的一些細節(jié)以及示例.

引入依賴

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>

我們引入這個依賴后,發(fā)現(xiàn)也引入了Hibernate的包,這是現(xiàn)在一種默認的做法,Hibernate已經(jīng)被作為JPA規(guī)范的最好實現(xiàn)了.

配置我們的數(shù)據(jù)源以及JPA(Hibernate)

#配置模板 #https://docs.spring.io/spring-boot/docs/1.4.0.RELEASE/reference/html/common-application-properties.html#數(shù)據(jù)源 spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa spring.datasource.druid.write.username=root spring.datasource.druid.write.password=1 spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driverspring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpa spring.datasource.druid.read.username=root spring.datasource.druid.read.password=1 spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver#JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration) spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.jpa.database=mysql spring.jpa.generate-ddl=true #就是hibernate.hbm2ddl.auto,具體說明可以看README spring.jpa.hibernate.ddl-auto=update #通過方法名解析sql的策略 spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultComponentSafeNamingStrategy spring.jpa.show-sql=true #spring.jpa.properties.* #spring.jpa.properties.hibernate.hbm2ddl.auto=update #spring.jpa.properties.hibernate.show_sql=true #spring.jpa.properties.hibernate.use-new-id-generator-mappings=true

druid數(shù)據(jù)源注入

@Configuration public class DruidDataSourceConfig {/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.read")@Bean(name = "readDruidDataSource")public DataSource readDruidDataSource() {return new DruidDataSource();}/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.write")@Bean(name = "writeDruidDataSource")@Primarypublic DataSource writeDruidDataSource() {return new DruidDataSource();} }

EntityManagerFactory實例注入

EntityManagerFactory類似于Hibernate的SessionFactory,mybatis的SqlSessionFactory 總之,在執(zhí)行操作之前,我們總要獲取一個EntityManager,這就類似于Hibernate的Session, mybatis的sqlSession. 注入EntityManagerFactory有兩種方式,一種是直接注入EntityManagerFactory,另一種是通過 LocalContainerEntityManagerFactoryBean來間接注入.雖說這兩種方法都是基于 LocalContainerEntityManagerFactoryBean的,但是在配置上還是有一些區(qū)別.

  • 1.直接注入EntityManagerFactory

配置:通過spring.jpa.properties.*來配置Hibernate的屬性

spring.jpa.properties.hibernate.hbm2ddl.auto=update spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.use-new-id-generator-mappings=true @Configuration @EnableJpaRepositories(value = "com.lc.springBoot.jpa.repository",entityManagerFactoryRef = "writeEntityManagerFactory",transactionManagerRef="writeTransactionManager") public class WriteDataSourceConfig {@AutowiredJpaProperties jpaProperties;@Autowired@Qualifier("writeDruidDataSource")private DataSource writeDruidDataSource;/*** EntityManagerFactory類似于Hibernate的SessionFactory,mybatis的SqlSessionFactory* 總之,在執(zhí)行操作之前,我們總要獲取一個EntityManager,這就類似于Hibernate的Session,* mybatis的sqlSession.* @return*/@Bean(name = "writeEntityManagerFactory")@Primarypublic EntityManagerFactory writeEntityManagerFactory() {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);factory.setPackagesToScan("com.lc.springBoot.jpa.entity");factory.setDataSource(writeDruidDataSource);//數(shù)據(jù)源factory.setJpaPropertyMap(jpaProperties.getProperties());factory.afterPropertiesSet();//在完成了其它所有相關(guān)的配置加載以及屬性設(shè)置后,才初始化return factory.getObject();}/*** 配置事物管理器* @return*/@Bean(name = "writeTransactionManager")@Primarypublic PlatformTransactionManager writeTransactionManager() {JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();jpaTransactionManager.setEntityManagerFactory(this.writeEntityManagerFactory());return jpaTransactionManager;} }
  • 2.先注入LocalContainerEntityManagerFactoryBean,再獲取EntityManagerFactory

配置:

spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.jpa.database=mysql spring.jpa.generate-ddl=true #就是hibernate.hbm2ddl.auto,具體說明可以看README spring.jpa.hibernate.ddl-auto=update #通過方法名解析sql的策略,具體說明可以看README,這里就不配置了 spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultComponentSafeNamingStrategy spring.jpa.show-sql=true @Configuration @EnableJpaRepositories(value = "com.lc.springBoot.jpa.repository",entityManagerFactoryRef = "writeEntityManagerFactory",transactionManagerRef = "writeTransactionManager") public class WriteDataSourceConfig1 {@AutowiredJpaProperties jpaProperties;@Autowired@Qualifier("writeDruidDataSource")private DataSource writeDruidDataSource;/*** 我們通過LocalContainerEntityManagerFactoryBean來獲取EntityManagerFactory實例* @return*/@Bean(name = "writeEntityManagerFactoryBean")@Primarypublic LocalContainerEntityManagerFactoryBean writeEntityManagerFactoryBean(EntityManagerFactoryBuilder builder) {return builder.dataSource(writeDruidDataSource).properties(jpaProperties.getProperties()).packages("com.lc.springBoot.jpa.entity") //設(shè)置實體類所在位置.persistenceUnit("writePersistenceUnit").build();//.getObject();//不要在這里直接獲取EntityManagerFactory}/*** EntityManagerFactory類似于Hibernate的SessionFactory,mybatis的SqlSessionFactory* 總之,在執(zhí)行操作之前,我們總要獲取一個EntityManager,這就類似于Hibernate的Session,* mybatis的sqlSession.* @param builder* @return*/@Bean(name = "writeEntityManagerFactory")@Primarypublic EntityManagerFactory writeEntityManagerFactory(EntityManagerFactoryBuilder builder) {return this.writeEntityManagerFactoryBean(builder).getObject();}/*** 配置事物管理器* @return*/@Bean(name = "writeTransactionManager")@Primarypublic PlatformTransactionManager writeTransactionManager(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(writeEntityManagerFactory(builder));} }

對于這個配置

@Bean(name = "writeEntityManagerFactoryBean")@Primarypublic LocalContainerEntityManagerFactoryBean writeEntityManagerFactoryBean(EntityManagerFactoryBuilder builder) {return builder.dataSource(writeDruidDataSource).properties(jpaProperties.getProperties()).packages("com.lc.springBoot.jpa.entity") //設(shè)置實體類所在位置.persistenceUnit("writePersistenceUnit").build();//.getObject();//不要在這里直接獲取EntityManagerFactory}

getObject()方法可以獲取到EntityManagerFactory的實例,看似跟第一種沒有什么區(qū)別,但是我們不能直接用 getObject(),不然會獲取不到,報空指針異常.

讀寫分離配置

自定義注入AbstractRoutingDataSource

@Configuration public class DataSourceConfig {private final static String WRITE_DATASOURCE_KEY = "writeDruidDataSource";private final static String READ_DATASOURCE_KEY = "readDruidDataSource";/*** 注入AbstractRoutingDataSource* @param readDruidDataSource* @param writeDruidDataSource* @return* @throws Exception*/@Beanpublic AbstractRoutingDataSource routingDataSource(@Qualifier(READ_DATASOURCE_KEY) DataSource readDruidDataSource,@Qualifier(WRITE_DATASOURCE_KEY) DataSource writeDruidDataSource) throws Exception {DynamicDataSource dataSource = new DynamicDataSource();Map<Object, Object> targetDataSources = new HashMap();targetDataSources.put(WRITE_DATASOURCE_KEY, writeDruidDataSource);targetDataSources.put(READ_DATASOURCE_KEY, readDruidDataSource);dataSource.setTargetDataSources(targetDataSources);dataSource.setDefaultTargetDataSource(writeDruidDataSource);return dataSource;} }

自定義注解

@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface TargetDataSource {String dataSource() default "";//數(shù)據(jù)源}

使用ThreadLocal使數(shù)據(jù)源與線程綁定

public class DynamicDataSourceHolder {//使用ThreadLocal把數(shù)據(jù)源與當(dāng)前線程綁定private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();public static void setDataSource(String dataSourceName) {dataSources.set(dataSourceName);}public static String getDataSource() {return (String) dataSources.get();}public static void clearDataSource() {dataSources.remove();}} public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {//可以做一個簡單的負載均衡策略String lookupKey = DynamicDataSourceHolder.getDataSource();System.out.println("------------lookupKey---------"+lookupKey);return lookupKey;}}

定義切面

@Aspect@Componentpublic class DynamicDataSourceAspect {@Around("execution(public * com.lc.springBoot.jpa.service..*.*(..))")public Object around(ProceedingJoinPoint pjp) throws Throwable {MethodSignature methodSignature = (MethodSignature) pjp.getSignature();Method targetMethod = methodSignature.getMethod();if (targetMethod.isAnnotationPresent(TargetDataSource.class)) {String targetDataSource = targetMethod.getAnnotation(TargetDataSource.class).dataSource();System.out.println("----------數(shù)據(jù)源是:" + targetDataSource + "------");DynamicDataSourceHolder.setDataSource(targetDataSource);}Object result = pjp.proceed();//執(zhí)行方法DynamicDataSourceHolder.clearDataSource();return result;}}

原文鏈接:https://my.oschina.net/lengchuan/blog/882391

作者:輕易科技-輕易貸研發(fā)部 李水軍

總結(jié)

以上是生活随笔為你收集整理的springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。