一:与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服务器和应用启动,测试一下:
首先查询redis缓存,缓存中没有数据,然后查询数据库,数据缓存到redis,返回数据,我们来看看redis服务器
数据已经被放入redis缓存中,我们再次从页面查询一次:
没有查询数据库,queryData还是上次查询数据库的日志,但是页面显示正常,说明查询的是redis服务器
那如果我们想修改数据库的数据,会怎么样?
我们来看看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/
转载文章受原作者版权保护。转载请注明原作者出处!