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

相关代码:github OSCchina

JPA是什么

JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理Java应用中的关系数据.它包括以下几方面的内容:

  • 1.ORM映射 支持xml和注解方式建立实体与表之间的映射.
  • 2.Java持久化API 定义了一些常用的CRUD接口,我们只需直接调用,而不需要考虑底层JDBC和SQL的细节.
  • 3.JPQL查询语言 这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合.
    在工作中,我们都会用到ORM技术,比如Hibernate,JOOQ等,根据需求的不同,我们会采用不同的ORM框架,当我们需要 更换ORM框架来满足我们的需求时,由于不同ORM框架的实现,使用方式的区别以及各自为营,我们往往需要对代码进行重构.JPA的 出现就是为了解决这个问题,JPA充分吸收了现有一些ORM框架的优点,具有易于使用,伸缩性强等优点,为ORM技术提供了一套标准的 接口用来整合不同的ORM框架.

Hibernate对JPA的实现

JPA本身并不做具体的实现,而只是定义了一些接口规范,让其它ORM来具体的实现这些接口,就目前来说,对JPA规范实现最好的就是 Hibernate了.这里提一下Mybatis,Mybatis并没有实现JPA规范,它本身也不能算做一个真正的ORM框架.

Spring Data JPA是什么

Spring Data JPA只是Spring Data框架的一个模块,可以极大的简化JPA的使用,Spring Data JPA强大的地方还在于能够简化我们 对持久层业务逻辑的开发,通过规范持久层方法的名称,通过名称来判断需要实现什么业务逻辑,我们机会可以在不写一句sql,不做任何dao层 逻辑的情况下完成我们绝大部分的开发,当然,对于一些复杂的,性能要求高的查询,Spring Data JPA一样支持我们使用原生的sql.

在这里我们不过多的去介绍JPA以及Spring Data JPA,主要还是与SpringBoot集成的一些细节以及示例.

引入依赖

<!-- 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>

我们引入这个依赖后,发现也引入了Hibernate的包,这是现在一种默认的做法,Hibernate已经被作为JPA规范的最好实现了.

配置我们的数据源以及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.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数据源注入

@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 总之,在执行操作之前,我们总要获取一个EntityManager,这就类似于Hibernate的Session, mybatis的sqlSession. 注入EntityManagerFactory有两种方式,一种是直接注入EntityManagerFactory,另一种是通过 LocalContainerEntityManagerFactoryBean来间接注入.虽说这两种方法都是基于 LocalContainerEntityManagerFactoryBean的,但是在配置上还是有一些区别.

  • 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* 总之,在执行操作之前,我们总要获取一个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);//数据源factory.setJpaPropertyMap(jpaProperties.getProperties());factory.afterPropertiesSet();//在完成了其它所有相关的配置加载以及属性设置后,才初始化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") //设置实体类所在位置.persistenceUnit("writePersistenceUnit").build();//.getObject();//不要在这里直接获取EntityManagerFactory}/*** EntityManagerFactory类似于Hibernate的SessionFactory,mybatis的SqlSessionFactory* 总之,在执行操作之前,我们总要获取一个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") //设置实体类所在位置.persistenceUnit("writePersistenceUnit").build();//.getObject();//不要在这里直接获取EntityManagerFactory}

getObject()方法可以获取到EntityManagerFactory的实例,看似跟第一种没有什么区别,但是我们不能直接用 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 "";//数据源}

使用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 {@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("----------数据源是:" + targetDataSource + "------");DynamicDataSourceHolder.setDataSource(targetDataSource);}Object result = pjp.proceed();//执行方法DynamicDataSourceHolder.clearDataSource();return result;}}

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

作者:轻易科技-轻易贷研发部 李水军

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10 make命令的安装

1、下载MinGWMinGW官网下载&#xff1a;http://www.mingw.org &#xff0c;点击右上角Downloads 或者网盘下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1vQVKycK1TKVsnLV_OMgiCg 提取码&#xff1a;bbhl 点击下载 mingw-get-setup.exe 安装 mingw-get-setup.exe…

html中svg的css,HTML5 内联 SVG

什么是SVG&#xff1f;SVG 指可伸缩矢量图形 (Scalable Vector Graphics)SVG 用于定义用于网络的基于矢量的图形SVG 使用 XML 格式定义图形SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失SVG 是万维网联盟的标准SVG 的优势与其他图像格式相比(比如 JPEG 和 GIF)&#x…

fast-rcnn win10 tensorflow部署

1、下载代码https://github.com/chde222/Faster-RCNN-TensorFlow-Python3 2、安装所依赖包 pip install -r requirements.txt 或者单独利用pip install cython pip install easydict 3、在 ./data/coco/pythonAPI 下打开cmd运行&#xff1a; python setup.py build_ext --in…

如何找到python的安装路径_如何查看python的安装路径

展开全部 官方文档上有写的&#xff0c;sys.executable是当前Python解释器&#xff08;或者其他Python实现&#xff09;的路径。 1、安装mysql 首先到mysql官网e68a843231313335323631343130323136353331333365643662下载文件&#xff1a;mysql-installer-community.msi 安装过…

两个html之间传递对象,解决微信警告:该链接含有无法解析的地址链接-两个html之间的传值(JSON数据)...

最近微信公众号开发进入二期了&#xff0c;增添关于汽车租赁的商城模块。遇到界面传值数据问题。1.首先我用的方式是&#xff1a;location.href"sales-detail.html?id"escape(JSON.stringify(htmlObj));另外&#xff0c;在第二界面用&#xff1a;var obj JSON.parse…

vue 获取url地址的参数_Vue之vuerouter的使用

1. 什么是vue-router?所谓的vue-router, 通俗的来讲 就是路由 但是这个和后端路由是不同的, 这是前端路由,是url和单页面组件的对应关系, 也就是SPA(单页应用)的路径管理器。再通俗的说&#xff0c;vue-router就是WebApp的链接路径管理系统。vue-router是Vue.js官方的路由插件…

win10下openpose1.5安装

历经一个星期的安装挫折&#xff0c;终于安装成功了。赶紧记录一下。 1、准备所需资料 &#xff08;1&#xff09;下载cuda和cudnn。版本最好都是cuda10和cudnn10.我下载的是下图所示版本。 如果不是这个版本可能会出错&#xff0c;而且出错几率很高。本人就因为安装的cuda10…

div展示html文本,html – 使文本适合div

我一直在努力重新创建我在90年代创建的父亲网站(呃),我一直无法让文本适合div内部并水平对齐.我需要将文本放在一起,以便它们适合div.这是jsfiddle中页面的代码示例HTMLHomeInside StaffOur Mission示例CSSdiv img#header{width: 50%;height: 15%;margin-left: 125px;margin-ri…

ImportError: cannot import name 'pyopenpose' from 'openpose'错误解决方法

前提条件&#xff1a;openpose1.5配置过程前面都成功&#xff0c;c api成功运行&#xff0c;但是python api配置中&#xff0c;cmake也添加了build_python_path.运行中仍出现 ImportError: cannot import name pyopenpose from openpose 这个错误。 解决方法&#xff1a; 将你…

python语句join_详解Python中的join()函数的用法

原博文 2017-08-07 20:51 − 函数&#xff1a;string.join() Python中有join()和os.path.join()两个函数&#xff0c;具体作用如下&#xff1a; join()&#xff1a; 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串 &n...0584 相…

计算机网络期末考长沙学院,校内用-第二套计算机网络试卷A..doc

《计算机网络》课程考试 A卷题号一二三四五六总分合分人复核人满分得分一、单选题(在本题的每一小题的备选答案中&#xff0c;只有一个答案是正确的&#xff0c;请把你认为正确答案的题号&#xff0c;填入题干的括号内。多选不给分。每小题1分&#xff0c;共20分)得分评卷人复核…

python glob.glob使用

函数功能&#xff1a;匹配所有的符合条件的文件&#xff0c;并将其以list的形式返回 示例&#xff1a; 当前文件夹下有如下文件 import globlist glob.glob(‘*g’)print(list) 结果&#xff1a; [dog.1012.jpg, dog.1013.jpg, dog.1014.jpg, dog.1015.jpg, dog.1016.jpg]

nohup启动jar_nohup命令详解

nohup命令详解在我们想要把SpringBoot微服务工程部署到远程服务器时&#xff0c;会通过java -jar springboot.jar的方式启动SpringBoot微服务。但是当我们把运行这个命令的SSH客户端退出登录就会导致SpringBoot进程也一起停止了&#xff0c;然后当然就没法访问我们启动的项目了…

教师进修学校计算机教学反思,优秀教学反思

十一月优秀教学反思教学反思在上周我们学校迎来了鞍山市教师进修学校第七届“薪火计划”八年组英语的展示课。鞍山市教师进修学校之所以搞这样一个活动是为了给80后老师创造更多的学习和交流的机会&#xff0c;为了帮助80后更快更好地成长。我们学校之所以提供了这样的场所最为…

用Python批量更改图片大小

#提取目录下所有图片,更改尺寸后保存到另一目录 from PIL import Image import os.path import glob def convertjpg(jpgfile,outdir,width128,height128):imgImage.open(jpgfile)try:new_imgimg.resize((width,height),Image.BILINEAR) new_img.save(os.path.join(outdir,os…

python用pip安装pygame_安装pygame和pip的问题以及过程

1. 先安装pip(一个重要的工具cnqqtd) 2. 安装与python版和系统本相匹配的pygame 详细安装过程 Pip请到这里安装 https://pypi.python.org/pypi/pip#download 下载完成后,会获得一个叫git-pip.py的文件 • 打开git-pip.py文件存在的目录,按下shift rightClick • 打开windows Po…

计算机水平考试改革,浅析全国计算机等级考试改革及应对策略

[摘 要]针对吉林省全国计算机等级考试部分科目即将实行无纸化改革进行分析&#xff0c;结合近几年笔者指导学生参加全国计算机等级考试的教学实践&#xff0c;对新形式下的考试内容和方式进行分析&#xff0c;及时调整教与学的侧重点&#xff0c;以期很好地应对新形式下的考核…

plotloss记录

1、保存所有的loss all_loss[] all_loss.append(loss) fileopen(data.txt,w) file.write(all_loss) file.close() 2、画图 list [] with open(data.txt, r) as f:for line in f.readlines():arr line.split(,) print(arr.__len__()) arr[0]arr[0][1:] arr[-1]arr[-1][0:-2…

量子计算机怎么算有用,如何在量子计算机上实现经典计算

如何在量子计算机上实现经典计算已完成15 分钟现在你理解了要尝试解决的经典问题&#xff0c;来看看如何将这个问题描述转换为一个量子操作&#xff0c;它可以被 Grover 的搜索算法使用并在量子计算机上运行。如何在叠加态上进行计算&#xff1f;量子计算的关键特性之一是不仅能…

.net fileupload批量上传可删除_【JavaWeb基础】文件上传和下载(修订版)

前言只有光头才能变强。文本已收录至我的GitHub仓库&#xff0c;欢迎Star&#xff1a;https://github.com/ZhongFuCheng3y/3y什么是文件上传&#xff1f;文件上传就是把用户的信息保存起来。为什么需要文件上传&#xff1f;在用户注册的时候&#xff0c;可能需要用户提交照片。…