目录
一、创建maven工程
总听人说写一个 starter ,感觉很高大上一样的,没事,我们也弄一个简单的 starter ,只要引入了,就可以自动配置我们的 ebean 数据源,注意这里需要创建的是一个maven工程,项目的结构图如下:
二、maven依赖
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.alian.microservice</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>common-db</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--整合ebean-->
<dependency>
<groupId>io.github.hexagonframework.boot</groupId>
<artifactId>spring-boot-starter-data-ebean</artifactId>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
</dependency>
<!--dozermapper映射增强-->
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<inherited>false</inherited>
<executions>
<execution>
<id>spring-boot-repackage</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
三、编码
3.1、配置类
Config
package cn.alian.microservice.db.config;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("cn.alian.microservice.db")
public class Config {
@Bean
@ConditionalOnMissingBean
public Mapper mapper() {
return DozerBeanMapperBuilder.buildDefault();
}
}
这里扫描的目录不要错了哦,我们这里的java类都是在 cn.alian.microservice.db 这个下面,所以扫描这个,大家可以看我前面的目录结构。
3.2、Ebean封装类
EbeanService
package cn.alian.microservice.db.service;
import com.github.dozermapper.core.Mapper;
import io.ebean.EbeanServer;
import io.ebean.ExpressionList;
import io.ebean.PagedList;
import io.ebean.Query;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.ebean.util.Converters;
import org.springframework.stereotype.Service;
import java.util.stream.Collectors;
@Service
public class EbeanService {
@Autowired
private Mapper mapper;
@Autowired
private EbeanServer ebeanServer;//不要删除这个哦
//封装一个分页查询(其他的根据需要可以加其他的方法哦)
public <T, D> Page<D> pageDtoList(Pair<ExpressionList<T>, PageRequest> pair, Class<D> d) {
Page<T> page = pageList(pair);
return new PageImpl<>(page.getContent().stream().map(e -> mapper.map(e, d)).collect(Collectors.toList()),
page.getPageable(), page.getTotalElements());
}
public <T> Page<T> pageList(Pair<ExpressionList<T>, PageRequest> pair) {
ExpressionList<T> where = pair.getLeft();
PageRequest pageRequest = pair.getRight();
Query<T> query = where.order().getQuery().setMaxRows(pageRequest.getPageSize())
.setFirstRow((int) pageRequest.getOffset());
PagedList<T> pagedList = query.findPagedList();
return Converters.convertToSpringDataPage(pagedList, pageRequest.getSort());
}
}
以后可以根据项目需要写公共的操作方法,像我这里所有的项目引入这个就可以使用分页的方法了。
四、配置spring.factories
resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.alian.microservice.db.config.Config
这里的配置项就是我们的配置类,配置类会自动扫描我们指定的包,从而达到自动装配,尤其是那个
io.ebean.EbeanServer 类,它才是真正的关键哦, 不要因为本类没有用就删除哦。
五、打包发布脚本
deploy.bat
cd %~dp0
cd..
call mvn clean source:jar deploy -Dmaven.test.skip=true
cd bin
pause
install.bat
cd %~dp0
cd..
call mvn clean install -Dmaven.test.skip=true
cd bin
pause
如果是发布到私服就用第一个,如果是本地开发可以用第二个安装到本地。
六、使用
当任意项目需要使用我们自己写的starter,引入以下依赖即可(当然你还得加上跟数据库相关的配置,我们后面会有)
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>common-db</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
七、验证
由于我们在验证服务注册时,我们已经创建了order订单服务,我们只需要继续改造下就行了。
7.1、验证
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka注册中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--订单实体,自动生成ebean querybean-->
<dependency>
<groupId>cn.alian.domain</groupId>
<artifactId>domain-order</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!--自己写的db starter-->
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>common-db</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!--mysql数据库连接-->
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
7.2、配置文件
接下里就是你期待的配置文件,没错就是很普通的spring datasource的配置文件,看起来和 ebean 都没有关系, 是不是有种错觉,博主是不是粘贴错了? 来,我们验证下!
application.properties
#服务名
spring.application.name=order
#端口
server.port=7001
#eureka注册中心地址
eureka.client.serviceUrl.defaultZone=http://10.130.3.222:8761/eureka
#数据库配置
spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://10.130.3.99:3306/order?autoReconnect=true&useSSL=false
spring.datasource.username=alian
spring.datasource.password=Alian1223
spring.datasource.hikari.connection-timeout=5000
spring.datasource.hikari.maximum-pool-size=10
7.3、service层
TestDbService
package cn.alian.mall.order.service;
import cn.alian.domain.order.domain.Order;
import cn.alian.domain.order.domain.query.QOrder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class TestDbService {
public Order queryOrder(int id) {
Order order = new QOrder()._id().eq(id).findOne();
log.info("查询的结果:{}", order);
return order;
}
}
7.4、controller层
TestDbController
package cn.alian.mall.order.controller;
import cn.alian.domain.order.domain.Order;
import cn.alian.mall.order.service.TestDbService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Validated
@RestController
@RequestMapping({"/test"})
public class TestDbController {
@Autowired
private TestDbService testDbService;
@GetMapping("/getOrder")
public Order testOrder() {
return testDbService.queryOrder(1);
}
}
请求后能查询到数据库的数据:
{"id":1,"userId":8001,"goodsId":10001,"price":10,"num":3,"title":"数字藏品","orderStatus":"00","createTime":"2022-04-07T03:37:23.654","updateTime":"2022-04-07T03:37:23.893"}
事实证明,博主没有贴错吧,说明我们的Ebean的整合是可以用了,并且 Query Bean 也是可以用的。
特别提醒:
如果是使用 @PostConstruct 进行测试,还需要引入如下依赖
@Autowired
private EbeanServer ebeanServer;
不然就会有如下提示
Caused by: io.ebean.datasource.DataSourceConfigurationException: Configuration error creating DataSource for the default Database. This typically means a missing application-test.yaml or missing ebean-test dependency. See https://ebean.io/docs/trouble-shooting#datasource
at io.ebean.Ebean$ServerManager.<init>(Ebean.java:87) ~[ebean-12.2.6.jar:na]
at io.ebean.Ebean$ServerManager.<init>(Ebean.java:50) ~[ebean-12.2.6.jar:na]
at io.ebean.Ebean.<clinit>(Ebean.java:45) ~[ebean-12.2.6.jar:na]
... 44 common frames omitted
Caused by: io.ebean.datasource.DataSourceConfigurationException: DataSource user is null?
at io.ebean.datasource.pool.ConnectionPool.<init>(ConnectionPool.java:220) ~[ebean-datasource-4.7.3.jar:na]
at io.ebean.datasource.core.Factory.createPool(Factory.java:15) ~[ebean-datasource-4.7.3.jar:na]
at io.ebeaninternal.server.core.DefaultContainer.getDataSourceFromConfig(DefaultContainer.java:290) ~[ebean-12.2.6.jar:na]
at io.ebeaninternal.server.core.DefaultContainer.setDataSource(DefaultContainer.java:234) ~[ebean-12.2.6.jar:na]
at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:100) ~[ebean-12.2.6.jar:na]
at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:70) ~[ebean-12.2.6.jar:na]
at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:36) ~[ebean-12.2.6.jar:na]
at io.ebean.EbeanServerFactory.create(EbeanServerFactory.java:58) ~[ebean-12.2.6.jar:na]
at io.ebean.Ebean$ServerManager.getWithCreate(Ebean.java:128) ~[ebean-12.2.6.jar:na]
at io.ebean.Ebean$ServerManager.<init>(Ebean.java:77) ~[ebean-12.2.6.jar:na]
... 46 common frames omitted
因为 Query Bean 就像一堆静态的方法,需要数据源初始化好了才能用,执行 @PostConstruct 时,ebean数据源可能还没有初始化,需要让容器扫描到才会加载, 这个"坑",我一般不告诉别人的。 当然如果你不是用的 @PostConstruct 测试就不用加了。