IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JavaEE——Spring Boot整合框架 -> 正文阅读

[Java知识库]JavaEE——Spring Boot整合框架

数据访问

准备数据库

CREATE DATABASE eshop;
USE eshop;
#创建用户表
CREATE TABLE userinfo (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
userName VARCHAR(20) NOT NULL , #用户名称
userPass VARCHAR(48) NOT NULL, #用户密码
birthday DATE DEFAULT NULL , #生日
gender CHAR(1) DEFAULT NULL , #性别
address VARCHAR(256) DEFAULT NULL #地址
);
#商品表
CREATE TABLE goods (
id INT AUTO_INCREMENT PRIMARY KEY,
goodsname VARCHAR(32), #商品名称
price FLOAT(10,1), #商品定价
memo TEXT , #商品描述
pic VARCHAR(200) , #商品图片
createtime DATETIME #生产日期
);
#订单表
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,#订单号
userid INT , #下单用户id
createtime DATETIME NOT NULL, #创建订单时间
memo VARCHAR(100) #备注
);
#外键:订单表userid引用userinfo的id
ALTER TABLE orders ADD CONSTRAINT fk_orders_userinfo_id FOREIGN KEY (userid)
REFERENCES userinfo (id);
#订单明细表
CREATE TABLE orderdetail (
id INT AUTO_INCREMENT PRIMARY KEY,
orderid INT NOT NULL , #订单id
goodsid INT NOT NULL , #商品id
itemsnum INT DEFAULT NULL #商品购买数量
);
#外键:orderdetail的ordersid引用表orders表的id
ALTER TABLE orderdetail ADD CONSTRAINT fk_orderdetail_orders_id FOREIGN KEY
(orderid)
REFERENCES orders (id);
#外键:orderdetail的goodsid引用表goods表的id
ALTER TABLE orderdetail ADD CONSTRAINT fk_orderdetail_goods_id FOREIGN KEY
(goodsid)
REFERENCES goods (id);
#初始化用户数据
INSERT INTO userinfo(userName,userPass,birthday,gender,address)
VALUES('admin','admin','1980-10-10','男','陕西西安');
INSERT INTO userinfo(userName,userPass,birthday,gender,address)
VALUES('林冲','lichong','1982-11-10','男','河南开封');
INSERT INTO userinfo(userName,userPass,birthday,gender,address)
VALUES('扈三娘','husanniang','1981-03-10','女','山东聊城');
INSERT INTO userinfo(userName,userPass,birthday,gender,address)
VALUES('孙二娘','sunerniang','1979-03-10','女','山东曾头市');
#初始化商品数据
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('平谷大桃','33.6','产自河北','pinggudatao.jpg','2017-12-12 12:12:12');
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('油桃','17.6','产自河北','youtao.jpg','2017-12-13 12:12:12');
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('水蜜桃','39.6','产自河北','shuimitao.jpg','2017-12-14 12:12:12');
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('蟠桃','33.6','产自河北','pantao.jpg','2017-12-11 12:12:12');
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('毛桃','31.6','产自河北','maotao.jpg','2017-10-12 12:12:12');
INSERT INTO goods(goodsname,price,memo,pic,createtime)
VALUES('樱桃','43.6','产自河北','yingtao.jpg','2017-11-22 12:12:12');
#初始化一条订单
INSERT INTO orders(userid,createtime,memo)
VALUES(2,'2017-09-21 16:26:51','要新鲜的');
#初始化订单明细
INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(1,1,3);
INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(1,2,2);
#初始化一条订单
INSERT INTO orders(userid,createtime,memo)
VALUES(2,'2017-09-22 16:26:50','和上次的一样');
#初始化订单明细
INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(2,1,3);
INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(2,2,2);

整合Mybatis

新建模块,名称:springboot004

第一步:创建项目

在这里插入图片描述
在这里插入图片描述

第二步:在 pom.xml 中添加相关 jar 依赖

<!--MyBatis 整合 SpringBoot 的起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>

<!--MySQL 的驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

提示:MySQL 的驱动依赖的版本由父工程管理

第三步:配置数据源

SpringBoot2.6.0版本默认使用Hikari数据源

#配置数据库的连接信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=

第四步:编写Model类

在com.ltw.model包中创建实体类

//使用lombok
public class Goods {
private Integer id;
private String goodsname;
private Double price;
private String memo;
private String pic;
private Date createtime;
}

第四步:编写Controller

在com.ltw.controller包中创建控制器
请求/goods/list
响应JSON

@Controller
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private IGoodsService goodsService;
@RequestMapping("/list")
public @ResponseBody Object list(){
List<Goods> list = goodsService.selectList();
return list;
}
public IGoodsService getGoodsService() {
return goodsService;
}
public void setGoodsService(IGoodsService goodsService) {
this.goodsService = goodsService;
}
}

第五步:编写Service接口和实现类

在com.ltw.service包中创建业务接口
Service接口

public interface IGoodsService {
List<Goods> selectList();
}

在com.ltw.service.impl包中创建业务实现
Service实现

@Service
public class GoodsService implements IGoodsService {
@Autowired
private IGoodsMapper goodsMapper;
@Override
public List<Goods> selectList() {
return goodsMapper.selectList();
}
public IGoodsMapper getGoodsMapper() {
return goodsMapper;
}
public void setGoodsMapper(IGoodsMapper goodsMapper) {
this.goodsMapper = goodsMapper;
}
}

在这里插入图片描述

第六步:编写Mapper接口

在com.ltw.mapper包中创建Mapper接口

@Mapper
public interface IGoodsMapper {
List<Goods> selectList();
}

@Mapper注解创建了Mapper对象,并交给spring容器管理

第七步:编写Mapper映射

在com.ltw.mapper包中创建Mapper映射配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ltw.mapper.IGoodsMapper">
<resultMap id="goodsMap" type="com.ltw.model.Goods">
<id column="id" property="id" />
<result column="goodsname" property="goodsname" />
<result column="price" property="price"/>
<result column="memo" property="memo"/>
<result column="pic" property="pic"/>
<result column="createtime" property="createtime"/>
</resultMap>
<select id="selectList" resultMap="goodsMap">
select * from goods
</select>
</mapper>

第八步:配置Mapper映射文件编译目录

<resources>
<!-- :默认情况下,Mybatis 的 xml 映射文件不会编译到 target 的 class 目录下,
所以我们需要在 pom.xml 文件中配置 resource,将映射文件编译到resource目录下 -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>

第九步:配置Mapper映射文件存储位置

#配置mapper映射文件存储位置
mybatis.mapper-locations=classpath:**/mapper/*.xml

**表示classpath目录及其所有的子目录

至此整合Mybatis完毕,完整的项目结构如下
在这里插入图片描述

第十步:启动测试

在这里插入图片描述

优化Mapper接口开发

@Mapper注解标注在Mapper接口上,实现了Mapper接口对象的创建
使用@MapperScan注解扫描包,可省去在每个Mapper接口上标注@Mapper

第一步:注释掉@Mapper注解

//@Mapper
public interface IGoodsMapper {
List<Goods> selectList();
}

第二步:打开@MapperScan注解

@SpringBootApplication
@MapperScan(basePackages = "com.kaifamiao.mapper")
public class Springboot005Application {
public static void main(String[] args) {
SpringApplication.run(Springboot005Application.class, args);
}
}

整合数据源

SpringBoot 2.6.0默认使用HikariDataSource,我们可以通过测试类确认SpringBoot使用的数据源。

测试默认数据源

在测试类中将Spring容器中的数据源对象注入给测试类的属性,输出类名。

@SpringBootTest
class Springboot005ApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() {
System.out.println(dataSource.getClass());
}
}

运行测试类,观察控制器输出结果如下:
在这里插入图片描述
证明默认使用的是Hikari数据源。
Springboot默认支持4种数据源类型,分别是:

  1. org.apache.tomcat.jdbc.pool.DataSource
  2. com.zaxxer.hikari.HikariDataSource
  3. org.apache.commons.dbcp.BasicDataSource
  4. org.apache.commons.dbcp2.BasicDataSource

对于这4种数据源,当 classpath 下有相应的类存在时,Springboot 会通过自动配置为其生成DataSourceBean,DataSourceBean默认只会生成一个,四种数据源类型的生效先后顺序如下:Tomcat–> Hikari --> Dbcp --> Dbcp2 。

切换成其他数据源

如果想更换成其他数据源,需要两个步骤,例如更换成Druid数据源。
第一步:导入数据源jar包

<!-- Druid数据源依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>

第二步:在application.properties中配置数据源

#数据源基本配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=
#切换成Druid数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

测试数据源切换是否成功
重新运行测试类

@SpringBootTest
class Springboot005ApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() {
System.out.println(dataSource.getClass());
}
}

运行测试类,观察控制器输出结果如下:
class com.alibaba.druid.pool.DruidDataSource
证明数据源已经切换成Druid。

数据源的基本配置

数据源的基本配置包括了
spring.datasource.driver-class-name
spring.datasource.url
spring.datasource.username
spring.datasource.password
以上四个数据源基本配置对于每一种数据源都是通用的。

数据源的其他信息

虽然数据源基本配置对于每一种数据源都是通用的,但是不同数据源连接池参数配置不是通用的。

测试连接池默认参数

现在数据源已经切换到Druid,Druid负责管理连接池,而连接池参数的设置是否合理在极大程度上影响程序运行的性能。那么此时Druid连接池参数是怎么设置的呢?
在调试模式下运行下面的测试,在控制台中观察默认情况下Druid的连接池参数默认设置。

@SpringBootTest
class Springboot005ApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
}
}

在这里插入图片描述
发现连接池初始化大小默认为0。如何设置连接池运行参数呢。
下面介绍如何配置德鲁伊数据源的连接池参数配置。

连接池其他参数设置

第一步:配置连接池参数
首先将德鲁伊连接池配置参数输入到application.properties配置文件中

#数据源连接池的参数配置
spring.datasource.initialSize: 5
spring.datasource.minIdle: 5
spring.datasource.maxActive: 20
spring.datasource.maxWait: 60000

第二步:自定义Druid数据源对象,交给spring容器管理
使用Java-based方式定义Druid数据源的bean对象,交给spring容器管理

package com.ltw.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
//@Configuration注解定义Bean的来源类
@Configuration
public class DruidConfig {
//@Bean将对象交给spring容器管理
@Bean
//@ConfigurationProperties注解将application.properties配置文件中前缀为
spring.datasource的属性注入给DruidDataSource的bean对象
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druid(){
return new DruidDataSource();
}
}

解释:
@ConfigurationProperties注解用于读取application.properties中的配置信息
参数prefix = "spring.datasource"表示读取以"spring.datasource"开头的配置信息,并按照"spring.datasource"后面的名称与Druid连接池参数名称相同注入属性值。
第三步:测试连接池其他参数设置
在调试模式下运行下面的测试,在控制台中观察默认情况下Druid的连接池参数默认设置。

@SpringBootTest
class Springboot005ApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
}
}

在这里插入图片描述
发现连接池初始化大小默认为5。application.perperties中连接池参数设置已经生效。

整合事务支持

Spring Boot 使用事务非常简单,底层依然采用的是 Spring 本身提供的事务管理

在入口类中使用注解 @EnableTransactionManagement 开启事务支持
在访问数据库的 Service 方法上添加注解 @Transactional 即可

事务执行的三种情况:
当方法内部抛出RuntimeException时事务回滚
当方法内部抛出Exception时事务提交
当方法内部没有抛出异常时事务提交

提示:事务是在业务层实现的

以添加订单为例,测试事务
一个订单中购买两件商品
向orders表中添加订单
向orderdetail表中添加订单中购买的商品

第一步:在Mapper接口中定义添加商品方法

public interface IOrdersMapper {
int insert(Orders record);
}
public interface IOrderdetailMapper {
int insert(Orderdetail record);
}

第二步:定义Mapper映射

<insert id="insert" parameterType="com.kaifamiao.model.Orders">
<selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO orders(userid,createtime,memo)
VALUES(#{userid},#{createtime},#{memo})
</insert>
<insert id="insert" parameterType="com.kaifamiao.model.Orderdetail" >
insert into orderdetail (id, orderid, goodsid, itemsnum)
values (#{id}, #{orderid}, #{goodsid}, #{itemsnum)
</insert>

第三步:在Service接口中定义添加商品方法

public interface IOrderService {
public void insert(Orders orders, Orderdetail orderdetail[]) throws
Exception;
}

注意:方法参数中包含了订单和订单中购买的商品

第四步:在Service实现类中实现添加商品方法

在insert方法上标注@Transactional注解,会在调用方法前开启事务,在方法调用结束后提交事务,在方法跑车RuntimeException时回滚事务。

/**
* 插入订单和订单明细,多条SQL语句应该在事务环境下执行
*/
@Transactional
public void insert(Orders orders, Orderdetail[] orderdetail) throws
Exception {
//orders插入到数据库,并获取出主键值
ordersMapper.insert(orders);
if(orderdetail!=null && orderdetail.length>0) {
for (int i = 0; i < orderdetail.length; i++) {
//订单的主键设置给订单明细的外键
orderdetail[i].setOrderid(orders.getId());
//orderdetail插入到数据库
orderdetailMapper.insert(orderdetail[i]);
}
}
}

第五步:编写控制器类

@RequestMapping("/insert")
public @ResponseBody String addOrder() throws Exception {
//创建订单,此时订单还没有编号
Orders orders = new Orders();
orders.setUserid(1);
orders.setMemo("发票一起寄出");
orders.setCreatetime(new Date());
//创建订单中购买的商品明细1,该明细中还没有订单号
Orderdetail orderdetail1 =new Orderdetail();
orderdetail1.setGoodsid(1);
orderdetail1.setItemsnum(3);
//创建订单中购买的商品明细2,该明细中还没有订单号
Orderdetail orderdetail2 =new Orderdetail();
orderdetail2.setGoodsid(1);
orderdetail2.setItemsnum(3);
//将商品明细封装到数组中国
Orderdetail orderdetails[] =new Orderdetail[]{
orderdetail1,
orderdetail2
};
orderService.insert(orders,orderdetails);
return "已添加订单";
}

第六步:在启动类上开启事务

@SpringBootApplication
@MapperScan(basePackages = "com.kaifamiao.mapper")
//开启事务支持(可选项,但业务方法上的@Transactional 必须添加)
@EnableTransactionManagement
public class Springboot005Application {
public static void main(String[] args) {
SpringApplication.run(Springboot005Application.class, args);
}
}

第七步:启动测试事务

测试业务方法正常执行

业务方法代码如下:程序正常运行,没有抛出异常,下单后提交事务,下单成功。

@Transactional
public void insert(Orders orders, Orderdetail[] orderdetail) throws
Exception {
//orders插入到数据库,并获取出主键值
ordersMapper.insert(orders);
if(orderdetail!=null && orderdetail.length>0) {
for (int i = 0; i < orderdetail.length; i++) {
//订单的主键设置给订单明细的外键
orderdetail[i].setOrderid(orders.getId());
//orderdetail插入到数据库
orderdetailMapper.insert(orderdetail[i]);
}
}
}

运行后查看数据库
在这里插入图片描述
结果显示:订单添加正常

测试方法抛出RuntimeException

业务方法代码中抛出运行时异常,事务回滚,下单失败。

@Transactional
public void insert(Orders orders, Orderdetail[] orderdetail) throws
Exception {
//orders插入到数据库,并获取出主键值
ordersMapper.insert(orders);
if(orderdetail!=null && orderdetail.length>0) {
for (int i = 0; i < orderdetail.length; i++) {
//订单的主键设置给订单明细的外键
orderdetail[i].setOrderid(orders.getId());
//orderdetail插入到数据库
orderdetailMapper.insert(orderdetail[i]);
throw new RuntimeException("事务中发生运行时异常");
}
}
}

运行后抛出异常如下:
在这里插入图片描述
由于抛出运行时异常,导致事务回滚,查看数据库,orders表和orderdetail表都没有新增记录,证明事务已经回滚。

测试方法抛出Exception

业务方法代码中抛出编译时异常,事务提交,但是下单失败,订单表中新增的记录与订单明细表中新增的记录不一致。

@Transactional
public void insert(Orders orders, Orderdetail[] orderdetail) throws
Exception {
//orders插入到数据库,并获取出主键值
ordersMapper.insert(orders);
if(orderdetail!=null && orderdetail.length>0) {
for (int i = 0; i < orderdetail.length; i++) {
//订单的主键设置给订单明细的外键
orderdetail[i].setOrderid(orders.getId());
//orderdetail插入到数据库
orderdetailMapper.insert(orderdetail[i]);
throw new Exception("事务中发生编译时异常");
}
}
}

运行后抛出异常如下:
在这里插入图片描述
由于抛出编译时异常,事务仍然提交,查看数据库,orders表中新增一条订单记录,orderdetail表中新增一条订单明细记录,丢失了一条订单明细记录,证明抛出编译时异常事务仍然提交,导致事务控制失败。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:27:33  更:2022-04-18 17:27:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:17:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码