前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot jpa搭建开发环境(一)

springboot jpa搭建开发环境(一)

作者头像
sucl
发布2019-08-07 11:53:38
7630
发布2019-08-07 11:53:38
举报
文章被收录于专栏:企业平台构建企业平台构建

随着spring4的出现,也为springboot奠定了基础,其实在了解spring4原理与一些扩展的同时,我们也就可以很方便搭建开发环境,而springboot就是使用了4中的一些新特性与功能,将我们搭建的过程进行了记录,同时通过一些特有的检测机制,实现各种环境的自由选择预搭配,将需要配置的功能模块全部优先实现,而作为开发者,需要做的就是选择。

这里用到springboot+jpa+layui来搭建一个后台管理模块,由于jpa是很纯粹的面向对象持久层标准,针对业务中大多是单表的操作非常适合,代码量会得到大量的简化,而且逻辑会比较清晰,同时内置很多接口能够为我们实现几乎所有的功能。

本次主要选用springboot1.x版本,同样是以maven项目为开端,如果是用idea,我们可以直接使用spring项目构建工具完成。

而我们需要引入的依赖主要的起始就两个:

代码语言:javascript
复制
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

由于多模块项目中,parent的引入能有一个,所以不通过spring-boot-starter-parent来控制其版本信息,该有如下:

代码语言:javascript
复制
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.10.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

之后同样,构建用户的增删改查模块,由实体类、dao、service、web几个层次组成:

由于hibernate属于jpa的一种实现,我们现在使用hibernate ddl语句自动实现数据库建表,但是前提是,表名与字段属性要定义完全,当然如何定义,之前在spring hibernate 中也有用到,完全一样的做法。

比如User实体:

代码语言:javascript
复制
@Data
@Entity
@Table(name = "USER")
public class User {

    @Id
    @Column(name = "USER_ID",length = 36)
    @GenericGenerator(name = "uuid",strategy = "uuid")
    @GeneratedValue(generator = "uuid")
    private String userId;

    @Column(name = "username",length = 24)
    private String username;

    @Column(name = "password",length = 56)
    private String password;

    @Column(name = "user_caption",length = 56)
    private String userCaption;

    @Column(name = "sex",length = 2)
    private String sex;

    @Column(name = "age",length = 3)
    private String age;

    @Column(name = "telephone",length = 16)
    private String telephone;

    @Column(name = "email",length = 56)
    private String email;

    @Column(name = "address",length = 128)
    private String address;

    @Column(name = "description",length = 256)
    private String description;
}

这里通过lombok插件减少代码量,需要注意的是,注解都是javax.persistence.*中的;

然后直接启动项目,对应的库中就会自动生成相应的表了。需要注意的是表字段顺序没有按照实体定义的先后,而是按照名称进行排序的。

下一步就是如何构建dao以及相关的服务了,其实在jpa中内置了很多接口,我们可以根据不同需要来进行实现,达到功能扩展的目的。

代码语言:javascript
复制
目前可用的接口有如下:
CrudRepository:实现基础的增删改查
PagingAndSortingRepository:对上一个接口的加强,实现分页排序
JpaRepository:对上一个接口的加强,同时添加excmole查询
JpaSpecificationExecutor:通过Criteria动态查询
Repository:标志接口

每一个接口都有相应的方法与使用场景,具体用到在看,目前按照我们的需要,只用继承JpaRepository就能完成基础的功能,代码很简单:

代码语言:javascript
复制
@Repository
public interface UserDao extends JpaRepository<User,String> {
}

具体的实现就不用我们再写了,这个已经由框架内部实现了,就好比mybatis定义接口而不用管实现,虽然实现方式上有些不同,但原理一样。

接下来就要写service层的逻辑了,由于对单表的操作无非就那几种,我们何不把这些操作全部抽象成共有方法,那样只用做简单的继承就可以实现90%的功能,不用重复做一些无意义的事。

所以构建一个BaseService:

代码语言:javascript
复制
public interface BaseService<R ,T> {

    T getById(Serializable id);

    T getOne(String property,Object value);

    List<T> getAll(Collection<Condition> conditions);

    List<T> getAll(T t);

    Pager<T> getPager(Pager pager,Collection<Condition> conditions,Collection<Order> orders);

    T save(T t);

    void saveBatch(Collection<T> ts);

    T updateById(T t);

    T saveOrUpdate(T t);

    void deleteById(Serializable id);

    void delete(String property,Object value);

    void delete(T t);

    void deleteAll(Collection<T> ts);

    boolean exist(Serializable id);

    boolean exist(T t);
}

那么如何实现这个service,并且作为公共服务可以实现代码复用,那么必须药用到一个东西,就是泛型,可以先看下实现如写的:

代码语言:javascript
复制
public abstract class BaseServiceImpl<R extends Repository<T,Serializable>,T> implements BaseService<R,T>{

    /**
     * 通过examle查询
     */
    protected JpaRepository<T,Serializable> repository;
    /**
     * 通过Specification查询
     */
    protected JpaSpecificationExecutor<T> specificationExecutor;

    protected abstract Class<T> getDomainClazz();

    @Resource
    public void setRepository(R r) {
        if(r instanceof JpaRepository){
            this.repository = (JpaRepository<T, Serializable>) r;
        }
        if(r instanceof JpaSpecificationExecutor){
            this.specificationExecutor = (JpaSpecificationExecutor<T>) r;
        }
    }

    @Override
    public T getById(Serializable id) {
        return repository.getOne(id);
    }

    @Override
    public T getOne(String property, Object value) {
        return repository.findOne(ConditionHelper.buildExample(getDomainClazz(),property,value));
    }

    @Override
    public List<T> getAll(Collection<Condition> conditions) {
        return specificationExecutor.findAll(ConditionHelper.buildSpecification(conditions));
    }

    @Override
    public List<T> getAll(T t) {
        return repository.findAll(Example.of(t));
    }

    @Override
    public Pager<T> getPager(Pager pager, Collection<Condition> conditions, Collection<Order> orders) {
        Pageable pageable = new PageRequest(pager.getPageIndex(),pager.getPageSize(),ConditionHelper.buildSort(orders));
        specificationExecutor.findAll(ConditionHelper.buildSpecification(conditions),pageable);
        return null;
    }

    @Override
    public T save(T t) {
        return repository.save(t);
    }

    @Override
    public void saveBatch(Collection<T> ts) {
        repository.save(ts);
    }

    @Override
    public T updateById(T t) {
        return repository.save(t);
    }

    @Override
    public T saveOrUpdate(T t) {
        return repository.save(t);
    }

    @Override
    public void deleteById(Serializable id) {
        repository.delete(id);
    }

    @Override
    public void delete(String property, Object value) {

    }

    @Override
    public void delete(T t) {
        repository.delete(t);
    }

    @Override
    public void deleteAll(Collection<T> ts) {
        repository.deleteInBatch(ts);
    }

    @Override
    public boolean exist(Serializable id) {
        return repository.exists(id);
    }

    @Override
    public boolean exist(T t) {
        return repository.exists(Example.of(t));
    }
}

可以看到,所有方法都是由Repository这个接口的子接口完成,具体实现有哪些上面提到过,现在主要使用,JpaRepository、JpaSpecificationExecutor,在dao中我们其实已经实现了这两个接口,那么为什么是这两个接口,因为JpaRepository包含了基本所有功能,而JpaSpecificationExecutor帮助我们更好的扩展功能。

其实在实现的过程中已经做了一些处理,比如分页查询、条件、排序相关参数的处理,这个处理方法因人而异,在这边主要是将查询条件封装成约定的对象,相关查询是基于此对象,然后如何构建,都是一套完整与匹配的构建过程。

其实到这里已经完成了出多了,现在在定义一个controller,同样作为基类共业务服务继承。

代码语言:javascript
复制
public class BaseController<S extends BaseService<?,T>,T> {

    @Autowired
    protected S s;

    @GetMapping("/{id}")
    public T get(@PathVariable String id){
        return s.getById(id);
    }

    @GetMapping
    public List<T> getAll(Collection<Condition> conditions){
        return  s.getAll(conditions);
    }

    @GetMapping(params = {"pageIndex","pageSize"})
    public Pager<T> getPager(Pager pager, Collection<Condition> conditions, Collection<Order> orders){
        return s.getPager(pager,conditions,orders);
    }

    @PostMapping
    public T saveOrUpdate(T t){
        return s.saveOrUpdate(t);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable String id){
        s.deleteById(id);
    }
}

之后就可以快速完成基础业务功能。

剩下还有很多模块没有完成,当然还有页面,之后会使用layui来实现。

后台代码:https://github.com/suspring/springboot-jpa-ms.git

下次将会在此基础上进行补充完善。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档