刚换了公司,项目架构师提出新的系统架构时还是愣了一下,搭建难度较低,很容易上手,但是对Spring Data JPA的了解不够深入,所以还是有些吃力,在框架搭建初期有许多东西并没有很好的集成。
20180714-这个项目表与表之间的耦合度太低了,且不允许在实体类中进行外键对象关联,一对多、多对一、多对多的关系处理就比较复杂了,Spring Data JPA提供了好几种不同的接口调用方式,因此什么时候使用什么样的方法显得尤为重要,不同的方法编写方式也不太一样,在数据处理方面比较头疼,如果需要抽取不同表之间的数据为结果,要做联合查询且需要额外在声明一个相应的实体类来接受,不然就只能将外键表字段存储到本表中,相当费劲。
框架体系
Spring Boot + Spring Data JPA + Spring Security + Spring Security oAuth2.0 + Thymeleaf
Spring Boot
Spring Data JPA
Spring Security
Thymeleaf
Vue.js
Vue Element-ui
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是点击无反应的。
来源:oschina
链接:https://my.oschina.net/u/1262063/blog/1851188