最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot集成Spring Data JPA及讀寫分離

 更新時間:2017年04月19日 15:03:05   投稿:mrr  
這篇文章主要介紹了SpringBoot集成Spring Data JPA及讀寫分離的相關知識,需要的朋友可以參考下

相關代碼: github OSCchina

JPA是什么

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

1.ORM映射 支持xml和注解方式建立實體與表之間的映射.

2.Java持久化API 定義了一些常用的CRUD接口,我們只需直接調用,而不需要考慮底層JDBC和SQL的細節(jié).

3.JPQL查詢語言 這是持久化操作中很重要的一個方面,通過面向對象而非面向數據庫的查詢語言查詢數據,避免程序的SQL語句緊密耦合.

在工作中,我們都會用到ORM技術,比如Hibernate,JOOQ等,根據需求的不同,我們會采用不同的ORM框架,當我們需要 更換ORM框架來滿足我們的需求時,由于不同ORM框架的實現,使用方式的區(qū)別以及各自為營,我們往往需要對代碼進行重構.JPA的 出現就是為了解決這個問題,JPA充分吸收了現有一些ORM框架的優(yōu)點,具有易于使用,伸縮性強等優(yōu)點,為ORM技術提供了一套標準的 接口用來整合不同的ORM框架.

Hibernate對JPA的實現

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

Spring Data JPA是什么

Spring Data JPA只是Spring Data框架的一個模塊,可以極大的簡化JPA的使用,Spring Data JPA強大的地方還在于能夠簡化我們 對持久層業(yè)務邏輯的開發(fā),通過規(guī)范持久層方法的名稱,通過名稱來判斷需要實現什么業(yè)務邏輯,我們機會可以在不寫一句sql,不做任何dao層 邏輯的情況下完成我們絕大部分的開發(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ā)現也引入了Hibernate的包,這是現在一種默認的做法,Hibernate已經被作為JPA規(guī)范的最好實現了,這里就不介紹Druid數據源的 配置了,大家可以看另外一篇XXXX.

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

#配置模板
#https://docs.spring.io/spring-boot/docs/1.4.0.RELEASE/reference/html/common-application-properties.html
#數據源
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.Driver
spring.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的策略,具體說明可以看README,這里就不配置了
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數據源注入

@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")
  @Primary
  public 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 {
  @Autowired
  JpaProperties jpaProperties;
  @Autowired
  @Qualifier("writeDruidDataSource")
  private DataSource writeDruidDataSource;
  /**
   * EntityManagerFactory類似于Hibernate的SessionFactory,mybatis的SqlSessionFactory
   * 總之,在執(zhí)行操作之前,我們總要獲取一個EntityManager,這就類似于Hibernate的Session,
   * mybatis的sqlSession.
   * @return
   */
  @Bean(name = "writeEntityManagerFactory")
  @Primary
  public EntityManagerFactory writeEntityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.lc.springBoot.jpa.entity");
    factory.setDataSource(writeDruidDataSource);//數據源
    factory.setJpaPropertyMap(jpaProperties.getProperties());
    factory.afterPropertiesSet();//在完成了其它所有相關的配置加載以及屬性設置后,才初始化
    return factory.getObject();
  }
  /**
   * 配置事物管理器
   * @return
   */
  @Bean(name = "writeTransactionManager")
  @Primary
  public 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 {
  @Autowired
  JpaProperties jpaProperties;
  @Autowired
  @Qualifier("writeDruidDataSource")
  private DataSource writeDruidDataSource;
  /**
   * 我們通過LocalContainerEntityManagerFactoryBean來獲取EntityManagerFactory實例
   * @return
   */
  @Bean(name = "writeEntityManagerFactoryBean")
  @Primary
  public LocalContainerEntityManagerFactoryBean writeEntityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
    return builder
        .dataSource(writeDruidDataSource)
        .properties(jpaProperties.getProperties())
        .packages("com.lc.springBoot.jpa.entity") //設置實體類所在位置
        .persistenceUnit("writePersistenceUnit")
        .build();
    //.getObject();//不要在這里直接獲取EntityManagerFactory
  }
  /**
   * EntityManagerFactory類似于Hibernate的SessionFactory,mybatis的SqlSessionFactory
   * 總之,在執(zhí)行操作之前,我們總要獲取一個EntityManager,這就類似于Hibernate的Session,
   * mybatis的sqlSession.
   * @param builder
   * @return
   */
  @Bean(name = "writeEntityManagerFactory")
  @Primary
  public EntityManagerFactory writeEntityManagerFactory(EntityManagerFactoryBuilder builder) {
    return this.writeEntityManagerFactoryBean(builder).getObject();
  }
  /**
   * 配置事物管理器
   * @return
   */
  @Bean(name = "writeTransactionManager")
  @Primary
  public PlatformTransactionManager writeTransactionManager(EntityManagerFactoryBuilder builder) {
    return new JpaTransactionManager(writeEntityManagerFactory(builder));
  }
}

對于這個配置

@Bean(name = "writeEntityManagerFactoryBean")
  @Primary
  public LocalContainerEntityManagerFactoryBean writeEntityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
    return builder
        .dataSource(writeDruidDataSource)
        .properties(jpaProperties.getProperties())
        .packages("com.lc.springBoot.jpa.entity") //設置實體類所在位置
        .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
   */
  @Bean
  public 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)
  @Documented
  public @interface TargetDataSource {
    String dataSource() default "";//數據源
  }

使用ThreadLocal使數據源與線程綁定

 public class DynamicDataSourceHolder {
    //使用ThreadLocal把數據源與當前線程綁定
    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 {
    @Override
    protected Object determineCurrentLookupKey() {
      //可以做一個簡單的負載均衡策略
      String lookupKey = DynamicDataSourceHolder.getDataSource();
      System.out.println("------------lookupKey---------"+lookupKey);
      return lookupKey;
    }
  }

定義切面

@Aspect
  @Component
  public 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("----------數據源是:" + targetDataSource + "------");
        DynamicDataSourceHolder.setDataSource(targetDataSource);
      }
      Object result = pjp.proceed();//執(zhí)行方法
      DynamicDataSourceHolder.clearDataSource();
      return result;
    }
  }

以上所述是小編給大家介紹的SpringBoot集成Spring Data JPA及讀寫分離,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

相關文章

  • SpringBoot項目運行jar包啟動的步驟流程解析

    SpringBoot項目運行jar包啟動的步驟流程解析

    這篇文章主要介紹了SpringBoot項目運行jar包啟動的步驟流程,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-07-07
  • java多線程應用實現方法

    java多線程應用實現方法

    以前沒有寫筆記的習慣,現在慢慢的發(fā)現及時總結是多么的重要了,呵呵。雖然才大二,但是也快要畢業(yè)了,要加油
    2012-11-11
  • SpringBoot使用MyBatis-Flex實現靈活的數據庫訪問

    SpringBoot使用MyBatis-Flex實現靈活的數據庫訪問

    MyBatisFlex是一款優(yōu)秀的持久層框架,本文主要介紹了SpringBoot使用MyBatis-Flex實現靈活的數據庫訪問,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • Spring?Cloud?Gateway中netty線程池優(yōu)化示例詳解

    Spring?Cloud?Gateway中netty線程池優(yōu)化示例詳解

    這篇文章主要介紹了Spring?Cloud?Gateway中netty線程池優(yōu)化示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • 關于Java中String類字符串的解析

    關于Java中String類字符串的解析

    這篇文章主要介紹有關Java中String類字符串的解析,在java中,和C語言一樣,也有關于字符串的定義,并且有他自己特有的功能,下面就進入主題一起學習下面文章內容吧
    2021-10-10
  • Mybatis SQL日志如何轉換為可執(zhí)行sql

    Mybatis SQL日志如何轉換為可執(zhí)行sql

    這篇文章主要介紹了Mybatis SQL日志如何轉換為可執(zhí)行sql問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 使用Digester解析XML文件的三種方式小結

    使用Digester解析XML文件的三種方式小結

    Digester是apache開源項目Commons中的一個子項目,用于解析XML文檔的工具,本文為大家整理了Digester解析XML文件的三種方式,希望對大家有所幫助
    2024-01-01
  • IDEA如何添加配置文件到classpath中

    IDEA如何添加配置文件到classpath中

    這篇文章主要介紹了IDEA如何添加配置文件到classpath中,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • 使用自定義注解和@Aspect實現責任鏈模式的組件增強的詳細代碼

    使用自定義注解和@Aspect實現責任鏈模式的組件增強的詳細代碼

    責任鏈模式是一種行為設計模式,其作用是將請求的發(fā)送者和接收者解耦,從而可以靈活地組織和處理請求,本文講給大家介紹如何使用自定義注解和@Aspect實現責任鏈模式的組件增強,文中有詳細的代碼示例供大家參考,感興趣的同學可以借鑒一下
    2023-05-05
  • 解決mybatis分頁插件PageHelper導致自定義攔截器失效

    解決mybatis分頁插件PageHelper導致自定義攔截器失效

    這篇文章主要為大家介紹了解決mybatis分頁插件PageHelper導致自定義攔截器失效方案示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08

最新評論

石泉县| 白银市| 汶川县| 安徽省| 吉水县| 望奎县| 那曲县| 鄂托克旗| 安康市| 嘉荫县| 黑水县| 西乡县| 仪征市| 晋江市| 波密县| 乌鲁木齐县| 贵南县| 沈阳市| 分宜县| 清苑县| 台州市| 莱阳市| 丹阳市| 皮山县| 民勤县| 定南县| 白银市| 东至县| 罗甸县| 丹江口市| 三门县| 班戈县| 松阳县| 桂阳县| 犍为县| 九龙县| 张家港市| 堆龙德庆县| 广元市| 九江县| 湟中县|