Spring Boot + Spring Data JPA 項目整合開發記錄(持續更新)

剛換了公司,項目架構師提出新的系統架構時仍是愣了一下,搭建難度較低,很容易上手,可是對Spring Data JPA的瞭解不夠深刻,因此仍是有些吃力,在框架搭建初期有許多東西並無很好的集成。前端

20180714-這個項目表與表之間的耦合度過低了,且不容許在實體類中進行外鍵對象關聯,一對多、多對1、多對多的關係處理就比較複雜了,Spring Data JPA提供了好幾種不一樣的接口調用方式,所以何時使用什麼樣的方法顯得尤其重要,不一樣的方法編寫方式也不太同樣,在數據處理方面比較頭疼,若是須要抽取不一樣表之間的數據爲結果,要作聯合查詢且須要額外在聲明一個相應的實體類來接受,否則就只能將外鍵表字段存儲到本表中,至關費勁。vue

 框架體系java

Spring Boot + Spring Data JPA + Spring Security + Spring Security oAuth2.0 + Thymeleafnode

Spring Bootwebpack

Spring Data JPAweb

Spring Securityspring

Thymeleafexpress

Vue.jsapache

Vue Element-uinpm

Node.js 與 NPM(輔助,安裝Node後,NPM會附帶安裝),附帶webpack工具、路由等。

實體類中並無聲明任何外鍵關聯關係,所以咱們查詢了許多種方法來解決外鍵關聯查詢並返回結果的方法。

Spring Data JPA - JpaRepository

Spring Data JPA - PagingAndSortingRepository

Spring Data JPA - JpaSpecificationExecutor

Spring Data JPA - Query

Spring Data JPA - QueryDSL

Spring Data JPA - CriteriaBuilder

NPM安裝與配置:

配置npm的全局模塊的存放路徑以及cache的路徑,在node根目錄下創建node_cache和node_global文件夾。

啓動CMD,輸入如下命令:

npm config set prefix "D:\DevelopTool\nodejs\node_global"
以及
npm config set cache "D:\DevelopTool\nodejs\node_cache"

安裝(Express)測試模塊,輸入如下命令,-g表明將該插件安裝到全局目錄中,node_golbal。

npm install express -g

設置環境變量,用戶變量下新建"NODE_PATH",輸入」D:\DevelopTool\Nodejs\node_global「。

用戶變量,修改"PATH",添加「%NODE_PATH%;」。

在D:\DevelopTool\nodejs\node_modules\npm目錄下,使用命令行進行安裝。

# install dependency
npm install

# develop
npm run dev

 

Spring Boot 與 Spring MVC的區別?

Spring 框架就像一個家族,有衆多衍生產品例如 MVC、boot、security、jpa等等。但他們的基礎都是Spring 的 ioc和 aop ioc 提供了依賴注入的容器 aop ,解決了面向橫切面的編程,而後在此二者的基礎上實現了其餘延伸產品的高級功能。

Spring MVC是一個前端框架。Spring MVC是基於 Servlet 的一個 MVC 框架 主要解決 WEB 開發的問題,由於 Spring 的配置很是複雜,各類XML、 JavaConfig、hin處理起來比較繁瑣。

Spring Boot換而言之,是一個Spring框架的一種形式。

Spring Boot實現了自動配置,下降了項目搭建的複雜度。

衆所周知Spring框架須要進行大量的配置,Spring Boot引入自動配置的概念,讓項目設置變得很容易。Spring Boot自己並不提供Spring框架的核心特性以及擴展功能,只是用於快速、敏捷地開發新一代基於Spring框架的應用程序。也就是說,它並非用來替代Spring的解決方案,而是和Spring框架緊密結合用於提高Spring開發者體驗的工具。同時它集成了大量經常使用的第三方庫配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot應用中這些第三方庫幾乎能夠零配置的開箱即用(out-of-the-box),大部分的Spring Boot應用都只須要很是少許的配置代碼,開發者可以更加專一於業務邏輯。、

DAO層代碼示例-20180720從新更新代碼(使用countBy、getBy、findBy等內部規定表達式能夠完成簡單的操做,後續And等,帶實體類對應的屬性名稱便可)

package com.hz.partyorg.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;

import com.hz.partyorg.entity.PartyOrgDeclareBasic;

import java.util.List;

/**
 * 黨組織-申報信息與基本信息聯合記錄
 * @author Wen.C
 */
public interface PartyOrgDeclareBasicDAO extends JpaRepository<PartyOrgDeclareBasic, Long>, 
PagingAndSortingRepository<PartyOrgDeclareBasic,Long>, 
JpaSpecificationExecutor<PartyOrgDeclareBasic> {

    Long countByDzzSbxxId(String dzzSbxxId);

    PartyOrgDeclareBasic getByDzzJbxxIdAndDzzSbxxId(String dzzJbxxId, String dzzSbxxId);

    PartyOrgDeclareBasic getByDzzSbxxIdAndAuditStatus(String dzzSbxxId, String auditStatus);

    List<PartyOrgDeclareBasic> findByDzzSbxxIdAndAuditStatus(String dzzSbxxId, String auditStatus);
}

Service層示例-20180720從新更新代碼

package com.hz.partyorg.service;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.hz.common.config.GlobalConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import com.hz.partyorg.dao.PartyOrgDeclareBasicDAO;
import com.hz.partyorg.entity.PartyOrgDeclareBasic;

/**
 * 黨組織-申報信息與基本信息聯合記錄
 * @author Wen.C
 */
@Service
public class PartyOrgDeclareBasicService {

	@Autowired
    private PartyOrgDeclareBasicDAO partyOrgDeclareBasicDAO;
	
	/**
     * 黨組織-申報信息與基本信息聯合記錄-保存數據
     * @param partyOrgDeclareBasic
     */
    public PartyOrgDeclareBasic save(PartyOrgDeclareBasic partyOrgDeclareBasic) {
        return partyOrgDeclareBasicDAO.save(partyOrgDeclareBasic);
    }

    /**
     * 黨組織-申報信息-列表查詢,根據傳入Type判斷,標記爲是否爲 0-須要審批的數據 1-歷史數據
     * @param type 0-須要審批的數據 1-歷史數據 null-取消條件
     * @param partyOrgDeclareBasic 實體對象
     * @return
     */
    public List<PartyOrgDeclareBasic> list(Integer type, PartyOrgDeclareBasic partyOrgDeclareBasic){
        Specification<PartyOrgDeclareBasic> spec = new Specification<PartyOrgDeclareBasic>() {
            @Override
            public Predicate toPredicate(Root<PartyOrgDeclareBasic> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                if(null != type && 0 == type){ // 0-須要審批的數據
                    list.add(cb.notEqual(root.get("auditStatus"), GlobalConfig.AUDIT_STATUS_TRANSFER_YES));
                    list.add(cb.notEqual(root.get("auditStatus"), GlobalConfig.AUDIT_STATUS_YES));
                } else if(null != type && 1 == type){ // 1-歷史數據
                    list.add(cb.notEqual(root.get("auditStatus"), GlobalConfig.AUDIT_STATUS_WAITE));
                    list.add(cb.notEqual(root.get("auditStatus"), GlobalConfig.AUDIT_STATUS_TRANSFER));
                }
                if(StringUtils.isNotEmpty(partyOrgDeclareBasic.getDzzJbxxId()) && StringUtils.isNotBlank(partyOrgDeclareBasic.getDzzJbxxId())){
                    list.add(cb.equal(root.get("dzzJbxxId"), partyOrgDeclareBasic.getDzzJbxxId()));
                }
                if(StringUtils.isNotEmpty(partyOrgDeclareBasic.getDzzSbxxId()) && StringUtils.isNotBlank(partyOrgDeclareBasic.getDzzSbxxId())){
                    list.add(cb.equal(root.get("dzzSbxxId"), partyOrgDeclareBasic.getDzzSbxxId()));
                }
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return partyOrgDeclareBasicDAO.findAll(spec ,new Sort(Sort.Direction.DESC, "id"));
    }
    
    /**
     * 黨組織-申報信息-分頁查詢
     * @param partyOrgDeclareBasic 實體對象
     * @param pageNo 當前頁碼
     * @param pageSize 顯示條數
     * @return
     */
    public Page<PartyOrgDeclareBasic> page(PartyOrgDeclareBasic partyOrgDeclareBasic, Integer pageNo, Integer pageSize){
        Specification<PartyOrgDeclareBasic> spec = new Specification<PartyOrgDeclareBasic>() {
            @Override
            public Predicate toPredicate(Root<PartyOrgDeclareBasic> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                if(StringUtils.isNotEmpty(partyOrgDeclareBasic.getDzzSbxxId()) && StringUtils.isNotBlank(partyOrgDeclareBasic.getDzzSbxxId())){
                    list.add(cb.equal(root.get("dzzSbxxId"), partyOrgDeclareBasic.getDzzSbxxId()));
                }
                if(StringUtils.isNotEmpty(partyOrgDeclareBasic.getDzzJbxxId()) && StringUtils.isNotBlank(partyOrgDeclareBasic.getDzzJbxxId())){
					list.add(cb.equal(root.get("dzzJbxxId"), partyOrgDeclareBasic.getDzzJbxxId()));
				}
                if(StringUtils.isNotEmpty(partyOrgDeclareBasic.getAuditResultsTime()) && StringUtils.isNotBlank(partyOrgDeclareBasic.getAuditResultsTime())){
					list.add(cb.equal(root.get("auditResultsTime"), partyOrgDeclareBasic.getAuditResultsTime()));
				}
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return partyOrgDeclareBasicDAO.findAll(spec ,new PageRequest(pageNo, pageSize, new Sort(Sort.Direction.DESC, "id")));
    }
    
    /**
     * 黨組織-申報信息-分頁查詢(判斷條件:auditResultsTime 審批時間 不爲空)
     * @param partyOrgDeclareBasic 實體對象
     * @param pageNo 當前頁碼
     * @param pageSize 顯示條數
     * @return
     */
    public Page<PartyOrgDeclareBasic> pageByAuditResultTimeIsNotNull(PartyOrgDeclareBasic partyOrgDeclareBasic, Integer pageNo, Integer pageSize){
        Specification<PartyOrgDeclareBasic> spec = new Specification<PartyOrgDeclareBasic>() {
            @Override
            public Predicate toPredicate(Root<PartyOrgDeclareBasic> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                if(null != partyOrgDeclareBasic.getDzzJbxxId() && StringUtils.isNotBlank(partyOrgDeclareBasic.getDzzJbxxId())){
					list.add(cb.equal(root.get("dzzJbxxId"), partyOrgDeclareBasic.getDzzJbxxId()));
				}
				    list.add(root.get("auditResultsTime").isNotNull());
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return partyOrgDeclareBasicDAO.findAll(spec ,new PageRequest(pageNo, pageSize, new Sort(Sort.Direction.DESC, "id")));
    }

    /**
     * 根據黨組織ID查詢記錄總數
     * @param dzzSbxxId
     * @return
     */
    public Long countByDzzSbxxId(String dzzSbxxId) {
        return partyOrgDeclareBasicDAO.countByDzzSbxxId(dzzSbxxId);
    }

    /**
     * 根據黨組織Id和申報信息Id查詢指定數據
     * @param dzzJbxxId
     * @param dzzSbxxId
     * @return
     */
    public PartyOrgDeclareBasic getByDzzJbxxIdAndDzzSbxxId(String dzzJbxxId, String dzzSbxxId) {
        return partyOrgDeclareBasicDAO.getByDzzJbxxIdAndDzzSbxxId(dzzJbxxId, dzzSbxxId);
    }

    /**
     * 根據申報信息Id和審批狀態查詢指定數據
     * @param dzzSbxxId
     * @param auditStatus
     * @return
     */
    public PartyOrgDeclareBasic getByDzzSbxxIdAndAuditStatus(String dzzSbxxId, String auditStatus) {
        return partyOrgDeclareBasicDAO.getByDzzSbxxIdAndAuditStatus(dzzSbxxId, auditStatus);
    }

    /**
     * 根據申報信息Id和審批狀態查詢數據返回集合
     * @param dzzSbxxId
     * @param auditStatus
     * @return
     */
    public List<PartyOrgDeclareBasic> findByDzzSbxxIdAndAuditStatus(String dzzSbxxId, String auditStatus) {
        return partyOrgDeclareBasicDAO.findByDzzSbxxIdAndAuditStatus(dzzSbxxId, auditStatus);
    }
}

Manager特殊業務處理層與Dao同級存在,不一樣業務場景調用(用於關聯表查詢以及返回聯合數據結果)-20180720,使用到QueryDSL。

package com.hz.partyorg.dao;

import com.hz.partyorg.entity.*;
import com.hz.partyorg.vo.PartyOrgDeclareInformationVo;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 申報信息、申報與黨組織信息聯合處理類,聯合查詢,返回Vo實體類對象,自由封裝
 */
@Component
public class PartyOrgDeclareBasicManager {

    @Autowired
    @PersistenceContext
    private EntityManager entityManager;
    private JPAQueryFactory queryFactory;

    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    /**
     * 針對申報信息作的聯合查詢方法
     * @param dzzJbxxId 黨組織ID
     * @param dzzSbxxIds 申報信息ID 集合
     * @param pageNo 當前頁數
     * @param pageSize 每頁顯示條數
     * @return
     */
    public  Map<String,Object> findList(String dzzJbxxId, List<Long> dzzSbxxIds, Integer pageNo, Integer pageSize){

        Map<String,Object> result = new HashMap<>();
        QPartyOrgDeclareInformation partyOrgDeclareInformation = QPartyOrgDeclareInformation.partyOrgDeclareInformation;
        QPartyOrgDeclareBasic partyOrgDeclareBasic = QPartyOrgDeclareBasic.partyOrgDeclareBasic;

//        JPAQuery<PartyOrgDeclareInformation> jpaQuery = queryFactory.select(partyOrgDeclareInformation).from(partyOrgDeclareInformation)
//                .leftJoin(partyOrgDeclareBasic)
//                .on(partyOrgDeclareBasic.dzzSbxxId.eq(partyOrgDeclareInformation.id.toString()))
//                .where(partyOrgDeclareInformation.id.in(dzzSbxxIds));

        int jpaQueryPageAllNum = queryFactory.select(partyOrgDeclareInformation, partyOrgDeclareBasic)
                .from(partyOrgDeclareInformation)
                .innerJoin(partyOrgDeclareBasic)
                .on(partyOrgDeclareBasic.dzzSbxxId.eq(partyOrgDeclareInformation.id.stringValue()))
                .where(partyOrgDeclareInformation.id.in(dzzSbxxIds))
                .where(partyOrgDeclareBasic.dzzJbxxId.eq(dzzJbxxId))
                .fetch()
                .size();

        JPAQuery<Tuple> jpaQuery = queryFactory.select(partyOrgDeclareInformation, partyOrgDeclareBasic)
                .from(partyOrgDeclareInformation)
                .innerJoin(partyOrgDeclareBasic)
                .on(partyOrgDeclareBasic.dzzSbxxId.eq(partyOrgDeclareInformation.id.stringValue()))
                .where(partyOrgDeclareInformation.id.in(dzzSbxxIds))
                .where(partyOrgDeclareBasic.dzzJbxxId.eq(dzzJbxxId))
                .offset(pageNo)
                .limit(pageSize);

        List<Tuple> tuples = jpaQuery.fetch();
        List<PartyOrgDeclareInformationVo> voList = new ArrayList<>();
        if(null != tuples && !tuples.isEmpty()){
            for(Tuple tuple:tuples){
                PartyOrgDeclareInformation partyOrgDeclareInformationResult = tuple.get(0, PartyOrgDeclareInformation.class);
                PartyOrgDeclareBasic partyOrgDeclareBasicResult = tuple.get(1, PartyOrgDeclareBasic.class);
                PartyOrgDeclareInformationVo vo = new PartyOrgDeclareInformationVo();
                // 1- 申報信息
                vo.setId(partyOrgDeclareInformationResult.getId());
                vo.setDeclarationTypeName(partyOrgDeclareInformationResult.getDeclarationTypeName());
                vo.setDeclarationItem(partyOrgDeclareInformationResult.getDeclarationItem());
                vo.setDeclarationTime(partyOrgDeclareInformationResult.getDeclarationTime());
                vo.setDeclarer(partyOrgDeclareInformationResult.getDeclarer());
                vo.setDeclarationOrg(partyOrgDeclareInformationResult.getDeclarationOrg());
                vo.setAuditResults(partyOrgDeclareInformationResult.getAuditResults());
                // 2- 申報聯合信息
                vo.setAuditStatus(partyOrgDeclareBasicResult.getAuditStatus());
                vo.setAuditStatusName(partyOrgDeclareBasicResult.getAuditStatusName());
                vo.setAuditResultsTime(partyOrgDeclareBasicResult.getAuditResultsTime());
                vo.setDzzJbxxId(Long.valueOf(partyOrgDeclareBasicResult.getDzzJbxxId()));
                voList.add(vo);
            }
        }

        result.put("pageAllNum", jpaQueryPageAllNum);
        result.put("voList", voList);

        return result;
    }

}

知識點

Vue

路由跳轉:

this.$router.push({ path: '/partyAffairsManager/partyOrgLifeManager', query: { activeName: 'partyClassRegistration', show: true } });

 

常見問題

Swagger相關

問題描述:

1.主表設置一對多的實體類對應關係@OneToMany;

2.swagger掃描對應的包路徑;

報錯問題:

項目啓動報錯,註釋掉一對多關係後,可正常啓動。

at springfox.documentation.spring.web.readers.parameter.ModelAttributeParameterExpander.expand(ModelAttributeParameterExpander.java:110) ~[springfox-spring-web-2.6.1.jar:2.6.1]

解決辦法:

 

數據報錯 JPA 多對一屬性 persist出錯

問題描述:

1.從表設置多對一關係@ManyToOne

報錯問題:

進行數據保存時報錯。

detached entity passed to persis

解決方法:

 

@Query 註解動態查詢沒法使用LIMIT關鍵詞

JPQL和原生的SQL,JPQL沒有LIMIT關鍵詞

 

Vue Element-ui

相關命令:

# 安裝
npm install
# 版本查詢
npm ls element-ui
# 卸載
npm uninstall element-ui
# 從新安裝
npm i element-ui -S
# 啓動項目
npm run dev
# 安裝指定版本
npm install element-ui@2.3.7 -S

樹型控件 Treeselect

https://vue-treeselect.js.org/#customize-key-names

# 安裝命令
npm install --save @riophae/vue-treeselect

時間控件 Moment

# 安裝命令
npm install moment

 

Vue問題記錄:

若是沒有傳遞迴顯數據給表單對象,則回顯時,表單控件如Select是點擊無反應的。

相關文章
相關標籤/搜索