springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

一:与JPA规范整合

jpa是一套orm的规范,提供api接口,hirebnate就是对jpa的一套实现,下面我们看看springboot如何

与jpa整合

1:添加依赖和配置

java;gutter:true; org.springframework.boot spring-boot-starter-data-jpa</p> <pre><code> ;gutter:true;
#自动创建表
spring.jpa.hibernate.ddl-auto:update
#打印 sql 语句
spring.jpa.show-sql:true

2:定义service 、dao以及实体类

java;gutter:true; @Service public class StudentServiceImpl implements StudentService {</p> <pre><code>@Autowired private StudentDao studentDao; @Override public Student findById(Integer id) { Optional optional = studentDao.findById(id); if(optional.isPresent()){ return optional.get(); } return null; } @Override public Student insertStudent(Student student) { return studentDao.save(student); } </code></pre> <p>}</p> <pre><code> ;gutter:true;
@Repository
public interface StudentDao extends JpaRepository {

}

java;gutter:true; @Data @Entity @Table(name="student") public class Student {</p> <pre><code>@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name="name") private String name; @Column(name="cardId") private String cardId; </code></pre> <p>}</p> <pre><code> ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154151323-639442379.png) 服务启动从日志看,会创建表: ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154324011-1781115818.png) 测试类: ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154552515-1448054547.png) 生成insert语句,插入数据: ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154442278-1461833674.png) ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154407895-55686688.png) ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710154428855-1338299515.png) 与JPA整合完成,很简单 二:与atomikos整合,实现分布式事务 如果同时在一个方法内使用两个数据源,想实现事务,该怎么办? 1:添加依赖和配置 ;gutter:true;
org.springframework.boot
spring-boot-starter-jta-atomikos

java;gutter:true; Mysql 1 mysql.datasource.test1.url = jdbc:mysql://localhost:3306/enjoy?useUnicode=true&characterEncoding=utf-8 mysql.datasource.test1.username = root mysql.datasource.test1.password = root mysql.datasource.test1.minPoolSize = 3 mysql.datasource.test1.maxPoolSize = 25 mysql.datasource.test1.maxLifetime = 20000 mysql.datasource.test1.borrowConnectionTimeout = 30 mysql.datasource.test1.loginTimeout = 30 mysql.datasource.test1.maintenanceInterval = 60 mysql.datasource.test1.maxIdleTime = 60</p> <p>Mysql 2 mysql.datasource.test2.url =jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8 mysql.datasource.test2.username =root mysql.datasource.test2.password =root mysql.datasource.test2.minPoolSize = 3 mysql.datasource.test2.maxPoolSize = 25 mysql.datasource.test2.maxLifetime = 20000 mysql.datasource.test2.borrowConnectionTimeout = 30 mysql.datasource.test2.loginTimeout = 30 mysql.datasource.test2.maintenanceInterval = 60 mysql.datasource.test2.maxIdleTime = 60</p> <h1>日志级别</h1> <p>logging.level.root=info</p> <h1>所有包下面都以debug级别输出</h1> <h1>logging.level.org.springframework.*=debug</h1> <h1>sql日志</h1> <p>logging.level.com.xiangxue.atomikos.db1.dao=debug logging.level.com.xiangxue.atomikos.db2.dao=debug</p> <h1>热部署</h1> <h1>热部署生效</h1> <p>spring.devtools.restart.enabled=true</p> <h1>设置重启的目录</h1> <p>spring.devtools.restart.additional-paths=src/main/java</p> <h1>classpath目录下的WEB-INF文件夹内容修改不重启</h1> <p>spring.devtools.restart.exclude=WEB-INF/**</p> <pre><code> 将配置封装到对象上,使用@ConfigurationProperties注解,会把mysql.datasource.test1为前缀的配置封装到对应的属性上,维护到spring 容器缓存中 ;gutter:true;
@Data
@ConfigurationProperties(prefix = "mysql.datasource.test1")
public class DBConfig1 {
private String url;

private String username;

private String password;

private int minPoolSize;

private int maxPoolSize;

private int maxLifetime;

private int borrowConnectionTimeout;

private int loginTimeout;

private int maintenanceInterval;

private int maxIdleTime;

private String testQuery;
}

创建数据源DataSource、sqlSessionFactory以及sqlSessionTemplate对象,并且添加@MapperScan扫描,将MapperFactoryBean维护到spring容器中,

key为Mapper文件的全限定名类名,value为MapperFactoryBean对象

java;gutter:true; @Configuration @MapperScan(basePackages = "com.xiangxue.jack.atomikos.db1.dao", sqlSessionFactoryRef = "test1SqlSessionFactory",sqlSessionTemplateRef="test1SqlSessionTemplate") public class Db1Config {</p> <pre><code>@Autowired DBConfig1 testConfig; @Bean(name = "test1DataSource") public DataSource testDataSource() { MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource(); mysqlXaDataSource.setUrl(testConfig.getUrl()); mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXaDataSource.setPassword(testConfig.getPassword()); mysqlXaDataSource.setUser(testConfig.getUsername()); mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true); AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(mysqlXaDataSource); xaDataSource.setUniqueResourceName("test1DataSource"); xaDataSource.setMinPoolSize(testConfig.getMinPoolSize()); xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize()); xaDataSource.setMaxLifetime(testConfig.getMaxLifetime()); xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout()); try { xaDataSource.setLoginTimeout(testConfig.getLoginTimeout()); } catch (SQLException e) { e.printStackTrace(); } xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval()); xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime()); xaDataSource.setTestQuery(testConfig.getTestQuery()); return xaDataSource; } @Bean(name = "test1SqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); } @Bean(name = "test1SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } </code></pre> <p>}</p> <pre><code> 创建Mapper类: ;gutter:true;
public interface CommonMapper1 {

@Select("select * from people")
List listPeoples();

@Insert("insert into people(name) values(#{name})")
int addPeople(People people);
}

另一个数据源也需要创建DataSource、SqlSessionFactory、sqlSessionTemplate对象,扫描对应的Mapper接口文件路径,和上一个数据源创建方式一样

创建一个service的测试类:在方法上添加@Transactional注解,方法内部,两个不同的mapper新增数据,两个mapper对应不同的数据源

java;gutter:true; @Service public class AreaServiceImpl implements AreaService {</p> <pre><code>@Autowired private CommonMapper1 commonMapper1; @Autowired private CommonMapper2 commonMapper2; @Autowired TransactionManager transactionManager; @Transactional public int saveArea(ConsultConfigArea area) { System.out.println(transactionManager); JtaTransactionManager jtaTransactionManager = (JtaTransactionManager)transactionManager; System.out.println(jtaTransactionManager.getUserTransaction()); UserTransaction userTransaction = jtaTransactionManager.getUserTransaction(); People people = new People(); people.setName("Lucy"); int count = commonMapper1.addPeople(people); System.out.println("插入一条People,count:"+count); Student student = new Student(); student.setCardId("122334"); student.setName("hello"); int count1 = commonMapper2.addStudent(student); System.out.println("插入一条Student,count1:"+count1); int i = 10/0; return count; } </code></pre> <p>}</p> <pre><code> 先把会导致异常的这行代码注释掉: ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710160240405-958844729.png) ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710160306919-2081377862.png) ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710160319668-1519456033.png) ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710160326816-1814054194.png) 数据插入成功! 现在把会导致运行时异常的代码放开,看看效果 ![springboot分析——与其他组件的整合(JPA规范/atomikos/redis)](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/822721-20200710160506166-104653341.png) 数据没有插入,说明回滚成功! 三:与redis整合 1:添加依赖和配置 ;gutter:true;
org.springframework.boot
spring-boot-starter-data-redis

java;gutter:true;</p> <h1>Redis数据库索引(默认为0)</h1> <p>spring.redis.database=0</p> <h1>redis服务器地址</h1> <p>spring.redis.host=127.0.0.1</p> <h1>redis暴露端口</h1> <p>spring.redis.port=6379</p> <h1>redis服务器连接密码</h1> <p>spring.redis.password=</p> <h1>连接池最大连接</h1> <p>spring.redis.pool.max-active=8</p> <h1>连接池最大阻塞等待时间</h1> <p>spring.redis.pool.max-wait=-1</p> <h1>连接池中的最大空闲连接</h1> <p>spring.redis.pool.max-idle=8</p> <h1>连接池中的最小空闲连接</h1> <p>spring.redis.pool.min-idle=0</p> <h1>连接超时时间</h1> <p>spring.redis.timeout=5000</p> <pre><code> 2:创建缓存管理类 ;gutter:true;
@Configuration
@EnableCaching
public class RedisConfig {

//缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}

@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

RedisTemplate template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);

//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);

ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);

// 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet();

return template;
}
}

创建使用类:

java;gutter:true; @Component public class RedisServiceImpl implements RedisService{</p> <pre><code>@Autowired private UserMapper userMapper; @Cacheable(cacheNames = "redisCache",key = "'jack'+ #id") @Override public String queryData(String id) { System.out.println("RedisServiceImpl -- queryData"); List list = userMapper.queryUserById(id); return JSON.toJSONString(list); } @CachePut(cacheNames = "redisCache",key = "'jack'+ #id") @Override public String putCache(String id) { System.out.println("RedisServiceImpl -- putCache"); User user = new User(); user.setName("Tom"); user.setAge("30"); user.setId(id); userMapper.updateUser(user); return JSON.toJSONString(user); } </code></pre> <p>}

下面我们把redis服务器和应用启动,测试一下:

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

首先查询redis缓存,缓存中没有数据,然后查询数据库,数据缓存到redis,返回数据,我们来看看redis服务器

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

数据已经被放入redis缓存中,我们再次从页面查询一次:

没有查询数据库,queryData还是上次查询数据库的日志,但是页面显示正常,说明查询的是redis服务器

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

那如果我们想修改数据库的数据,会怎么样?

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

我们来看看redis内存库的数据会不会变化:

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

说明修改数据库的数据,redis会同步更新

这样springboot和redis的整合就完成了!!!

Original: https://www.cnblogs.com/warrior4236/p/13279914.html
Author: warrior1234
Title: springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529364/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 离线版centos8安装docker笔记

    嗨嗨哈哈,已经很久没有坐下来胡编乱造一点笔记了,平时云服务器搞惯了,一个命令就安装好了docker了的,但这次生不逢时的新机房就没那么幸运了,有多不逢时超乎想象,不仅仅服务器没有外…

    Linux 2023年6月14日
    088
  • 【转】认识长轮询:配置中心是如何实现推送的?

    一 前言 传统的静态配置方式想要修改某个配置时,必须重新启动一次应用,如果是数据库连接串的变更,那可能还容易接受一些,但如果变更的是一些运行时实时感知的配置,如某个功能项的开关,重…

    Linux 2023年6月16日
    0111
  • vscode搜索所有文件夹中所有文件的方法

    最近在看opencv相关的内容,看到画图这一部分时,提示我 这些代码都来自OpenCV代码的sample文件夹。 按照他的提示,我打开了相应的文件夹,却发现,so many 文件 …

    Linux 2023年6月14日
    0257
  • QT编程中的char*,wchar_t*与QString之间的转换

    //QString to wchar_t:const wchar_t * encodedName = reinterpret_cast Original: https://www….

    Linux 2023年6月14日
    079
  • 使用Supervisor监控mysql

    监控文件配置: [program:mysql] ; 管理的子程序名字,要和项目有关联,不能乱写command=/usr/local/mysql/bin/mysqld_safe &#…

    Linux 2023年6月6日
    047
  • mysql二进制安装脚本部署

    mysql二进制安装脚本部署 mysql二进制安装脚本部署 单实例 使用函数的单实例 使用函数的单实例或者多实例 单实例 [root@localhost ~]# mkdir mys…

    Linux 2023年6月6日
    0105
  • 数据库备份数据脚本

    #!/bin/bash currentpath=dirname $0 if [ ${currentpath} == ‘.’ ];then currentpath=pwd fi ba…

    Linux 2023年6月8日
    073
  • 2021年度总结 2022年度规划

    2021年 计划 1、学习更多的知识😁 2、学习408的知识,至少能熟悉计算机组成原理、操作系统、计算机网络、算法这几个的联系,区别等。😁 3、整理408的知识到博客上。 (一篇未…

    Linux 2023年6月13日
    089
  • Debian10 命令行启动

    打开 default grub 配置 $ sudo vi /etc/default/grub 修改以下3处内容 保存修改 更新grub配置 $ sudo update-grub 设…

    Linux 2023年5月27日
    095
  • Java实现栈

    package algorithm; import java.util.Arrays;import java.util.Iterator; /** @author Administ…

    Linux 2023年6月14日
    0106
  • 条件分支

    条件分支 if-else-fi [root@node1 test]# vim if.sh #!/bin/bash amswer=30 if [ $1 -gt $answer ];t…

    Linux 2023年6月11日
    071
  • PHP使用pdfparser实现对PDF转换成本文

    使用pdfparser对PDF转换成文本形式,转换后没有格式。 原始PDF: 转换成文本: 第一步:安装pdfparser composer require smalot/pdfp…

    Linux 2023年6月7日
    0108
  • .net core3.1 abp动态菜单和动态权限(动态菜单实现和动态权限添加) (三)

    我们来创建动态菜单吧 首先,先对动态菜单的概念、操作、流程进行约束:1.Host和各个Tenant有自己的自定义菜单2.Host和各个Tenant的权限与自定义菜单相关联2.Ten…

    Linux 2023年6月7日
    086
  • Podman基础用法

    Podman基础 1、什么是Podman? Podman是一种开源的Linux原生工具,旨在根据开放容器倡议(Open Container Initiative,OCI)标准开发、…

    Linux 2023年6月7日
    078
  • Teamviewer解决方式–Win10

    用teamviewer远程时,如果被检测为商用,会给出提示,表示本次远程只能持续几分钟。下面给出win10的解决方案。 1、卸载teamviewer 从控制面板-程序与功能中卸载 …

    Linux 2023年6月8日
    089
  • Python 内置logging 使用详细讲

    logging 的主要作用 提供日志记录的接口和众多处理模块,供用户存储各种格式的日志,帮助调试程序或者记录程序运行过程中的输出信息。 logging 日志等级 logging 日…

    Linux 2023年6月7日
    071
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球