目录
一、搭建父类工程
解析父工程中pom文件的标签:
二、搭建基础模块
Spring Data Jpa的作用
对Order类的解释:
三、搭建用户微服务模块
?? 一、创建pom.xml,继承父工程,依赖common模块
?? 二、配置文件内容如下:
四、搭建商品模块
一、配置文件
二、pom文件
三、项目结构
一、启动类(不要忘了扫描entity实体类)
二、控制层(@slf4j注解、@PathVariable的作用)
三、接口层
四、实现类与dao接口
疑问点一:为什么dao接口中并没有任何的方法,但是还是可以调用findById方法?
疑问点二:为什么接口调用方法后还需要调用get( )方法?
?五、搭建订单模块(跟商品模块差不多)
一、pom配置文件
二、项目启动配置文件
三、项目结构
?一、启动类
二、控制层(restTemplate调用product模块的方法)
三、接口层
四、实现类层
思考:为什么项目启动后数据库里面就会自动创建表呢?
一、搭建父类工程
也就是上图所示的shop-parent模块,创建maven项目后将src文件夹删除。
配置pom依赖:将打包方式设置为pom。
为什么要设置为pom?
<!--表示此工程是聚合工程-->
<!--pom 项目里没有java代码,也不执行任何代码, 只是为了聚合工程或传递依赖用的。
可以理解成是将多个model合并-->
pom.xml文件:
解析父工程中pom文件的标签:
properties:用于统一管理jar包版本
dependencyManagement:子模块继承之后,提供作用:锁定版本+子module不用写groupId和version
将单独的某个依赖设置为pom的作用:
使用<scope>import</scope>解决Maven项目单继承问题_明快de玄米61的博客-CSDN博客
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lay</groupId>
<artifactId>shop-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>shop-common</module>
<module>shop-user</module>
<module>shop-product</module>
<module>shop-order</module>
</modules>
<packaging>pom</packaging>
<!--表示此工程是聚合工程-->
<!--pom 项目里没有java代码,也不执行任何代码,
只是为了聚合工程或传递依赖用的。可以理解成是将多个model合并-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<!--表示编译的时候就会将这个jar导入子项目中-->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
二、搭建基础模块
创建 shop-common 模块(打包方式为jar),在pom.xml中添加依赖
?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>com.lay</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-common</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Spring Data Jpa的作用
在JPA规范基础下提供了 Repository 层的实现 ,?能够方便大家在不同的ORM框架之间进行切换而不要更改代码 .
PS : 我们用不同的ORM框架 , 在DAO层写业务代码会稍微有差异 , SpringDataJPA 就是为了解决这个出现的.
ORM:通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。本质就是将数据从一种形式转换到另外一种形式。
在实际的工程中,推荐采用Spring Data JPA + ORM(如:Hibernate)进行开发,这样在切换不同的ORM提供了方面,同时也使得Repository变得简单。程序低耦合。
MyBatis不是ORM框架,MyBatis只是将数据库中的内容映射为实体。没有将实体映射为数据库中的字段。
common层的结构:
对Order类的解释:
?使用@Entity去注释实体类时,需import javax.persistence.Entity
javax.persistence位于hibernate-jpa-**.jar包里面。
@Entity是指这个类映射到数据库表, 当你不使用这个类(被注解的类)时,后台不会对其进行处理,只有当你从数据库读取数据时,由于你要读取的表映射有实体类(被@Entity注释的), 那么后台应该会自动帮你实例化一个对象, 然后将数据库中的数据填充到对象中!
@Entity定义的对象将会成为被JPA管理的实体,将映射到指定的数据库表。
?@GeneratedValue
? ? ? ? ???指定主键的生成策略。有如下四个值
?-AUTO主键由程序控制, 是默认选项 ,不设置就是这个
?-IDENTITY 主键由数据库生成, 采用数据库自增长, Oracle不支持这种方式 ? ? -SEQUENCE 通过数据库的序列产生主键, MYSQL? 不支持 ? ? -Table 提供特定的数据库产生主键, 该方式更有利于数据库的移植
package com.lay.shop.entity;
import lombok.Data;
import javax.persistence.*;
//订单
//表明当前的类是实体类(与表对应的类),那么的值就是表名
@Entity(name = "shop_order")
@Data
public class Order {
//id表示是主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键值自动生成
private Long oid;//订单id
//当表的列名和属性名不同必须加column注解
@Column(name = "uid")
private Integer uid;//用户id
private String username;//用户名
private Integer pid;//商品id
private String pname;//商品名称
private Double pprice;//商品单价
private Integer number;//购买数量
}
三、搭建用户微服务模块
?? 一、创建pom.xml,继承父工程,依赖common模块
?? 二、配置文件内容如下:
server:
port: 8071
spring:
application:
name: service-user
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?serverTimezone=Asia/Shanghai
username: root
password: abc123
#解决时差问题
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
四、搭建商品模块
一、配置文件
server:
port: 8081
spring:
application:
name: service-product
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?serverTimezone=Asia/Shanghai
username: root
password: abc123
#解决时差问题
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
properties:
hibernate:
hbm2ddl:
#在项目启动时会检查对应的数据库中的表是否存在(依据实体类),如果不存在就创建!
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
二、pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>com.lay</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-product</artifactId>
<dependencies>
<dependency>
<groupId>com.lay</groupId>
<artifactId>shop-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
三、项目结构
一、启动类(不要忘了扫描entity实体类)
/**
* @author Dragon code!
* @create 2022-05-04 15:36
*/
@SpringBootApplication
@EntityScan(basePackages = "com.lay.shop.entity")
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class);
}
}
二、控制层(@slf4j注解、@PathVariable的作用、@Entity)
想看entity可以看上面,这里能得到product对象全靠Entity注解!(因为这里是hibernate框架)
package com.lay.shop.porduct.controller;
import com.alibaba.fastjson.JSON;
import com.lay.shop.entity.Product;
import com.lay.shop.porduct.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author Dragon code!
* @create 2022-05-04 15:47
*/
@RestController
//此注解来自于lombok
//用于生成log对象
@Slf4j
public class ProductController {
@Resource
private ProductService productService;
@RequestMapping("/product/{pid}")
//@PathVariable可以用来映射URL中的占位符到目标方法的参数中
public Product findByPid(@PathVariable("pid") Integer pid){
Product product = productService.findByPid(pid);
log.info("查询结果:"+ JSON.toJSONString(product));
return productService.findByPid(pid);
}
}
三、接口层
/**
* @author Dragon code!
* @create 2022-05-04 15:42
*/
public interface ProductService {
Product findByPid(Integer pid);
}
四、实现类与dao接口
/**
* @author Dragon code!
* @create 2022-05-04 15:39
*/
//泛型的第二个参数是实体类中主键的名称
public interface ProductDao extends JpaRepository<Product, Integer> {
}
/**
* @author Dragon code!
* @create 2022-05-04 15:43
*/
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductDao productDao;
@Override
public Product findByPid(Integer pid) {
return productDao.findById(pid).get();
}
}
疑问点一:为什么dao接口中并没有任何的方法,但是还是可以调用findById方法?
?答:其实是跟之前使用的通用mapper是一个道理,此时的dao接口继承于JpaRepository
????????那么该接口的泛型第一个参数为要操作的实体类,第二个参数为该实体类的主键类型
疑问点二:为什么接口调用方法后还需要调用get( )方法?
Spring Data JPA中的getOne,findOne以及findById_Tiger_Paul的博客-CSDN博客 答:其实通过jpa模板方法得到的结果是Optional类型的对象
?????? Java中的java.util.Optional类的get()方法用于获取此Optional实例的值
???? (也就是泛型指定的实体类的对象)。
如果此Optional实例中不存在任何值,则此方法将引发NullPointerException。 ?
启动项目:查看是否正常执行(成功)
五、搭建订单模块(跟商品模块差不多)
一、pom配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>com.lay</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-order</artifactId>
<dependencies>
<dependency>
<groupId>com.lay</groupId>
<artifactId>shop-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
二、项目启动配置文件
server:
port: 8091
spring:
application:
name: service-order
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?serverTimezone=Asia/Shanghai
username: root
password: abc123
#解决时差问题
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
properties:
hibernate:
hbm2ddl:
#在项目启动时会检查对应的数据库中的表是否存在(依据实体类),如果不存在就创建!
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
三、项目结构
一、启动类
- 同样是别忘了扫描实体类。
- 项目集成restTemplate模板所以启动类添加初始化方法,并将其交给容器管理,达到一启动项目就创建对象的效果
/**
* @author Dragon code!
* @create 2022-05-04 16:43
*/
@SpringBootApplication
@EntityScan(basePackages = "com.lay.shop.entity")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}
二、控制层(restTemplate调用product模块的方法)
注入restTemplate模板对象
作用是可以直接在后台发出基于http协议的rest风格的请求
那么控制层要做的是通过rest请求传id查询到一个product的对象,然后将其封装order对象里面,其他信息随便给,模拟产生订单!
重点在于getForObject方法()
一是请求,而是返回值的类型
/**
* @author Dragon code!
* @create 2022-05-04 16:46
*/
@RestController
@Slf4j
public class OrderController {
@Resource
private OrderService orderService;
@Resource
//可以发出基于http协议的rest风格的请求
private RestTemplate restTemplate;
@RequestMapping("/order/prod/{pid}")
public Order save(@PathVariable Integer pid){
log.info("准备调用商品服务查询商品信息");
Product product = restTemplate.getForObject("http://localhost:8081/product/" + pid, Product.class);
log.info("商品微服务返回的商品"+ JSON.toJSONString(product));
log.info("创建订单对象");
Order order = new Order();
order.setPname(product.getPname());
order.setPprice(product.getPprice());
order.setNumber(1);
order.setPid(product.getPid());
order.setUsername("测试用户");
orderService.save(order);
return order;
}
}
三、接口层
/**
* @author Dragon code!
* @create 2022-05-04 16:44
*/
public interface OrderService {
void save(Order order);
}
四、实现类层
/**
* @author Dragon code!
* @create 2022-05-04 16:45
*/
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private OrderDao orderDao;
@Override
public void save(Order order) {
orderDao.save(order);
}
}
同样的mapper层是利用的jpa的方法
/**
* @author Dragon code!
* @create 2022-05-04 16:44
*/
public interface OrderDao extends JpaRepository<Order,Long> {
}
最后效果:成功访问
数据插入成功
思考:为什么项目启动后数据库里面就会自动创建表呢?
@Entity注解配合项目启动配置文件中的jpa配置达到底层采用hibernate根据实体类建表的效果!
|