zoukankan      html  css  js  c++  java
  • SpringDataJpa2

    1.SpringDataJpa的扩展 — 抽取

    创建一个BaseRepository接口然后去继承JpaRepository和JpaSpecificationExecutor

    然后在里面写我们自己想要的方法

    在接口上边加上注解@NoRepositoryBean 这是为了防止底层去找SimpleJpaRepository的实现类 我们需要找我们自己的实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    * @NoRepositoryBean
    * 防止底层去找SimpleJpaRepository的实现类 我们需要找我们自己的实现类
    * */

    public interface <T,ID extends Serializable> extends JpaRepository<T, ID>,
    JpaSpecificationExecutor<T> {

    //根据BaseQuery拿到分页对象
    Page findPageByQuery(BaseQuery baseQuery);

    //根据BaseQuery拿到对应的数据 不分页
    List<T> findByQuery(BaseQuery baseQuery);

    //根据jpql与对应的参数拿到数据
    List findByJpql(String jpql,Object...value);

    }

    然后再创建一个实现类 实现我们刚写的BaseRepository接口

    再继承 SimpleJpaRepository

    这样就不用覆写SpringDataJpa本身的方法了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    * Serializable 序列化 用来网络传输
    * extends SimpleJpaRepository 不会覆写SpringDataJpa本身的方法
    * implements BaseRepository 实现自身的方法
    *
    *
    * */
    public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements <T,ID> {
    //让Spring把entityManager注入进来
    private EntityManager entityManager;

    //继承了SimpleJpaRepository中没有无参构造 必须覆写里面的有参构造
    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
    super(domainClass, em);
    this.entityManager = em;
    }
    //分页查询方法
    @Override
    public Page findPageByQuery(BaseQuery baseQuery) {
    //排序
    Sort sort = baseQuery.createSort();
    //条件
    Specification specs = baseQuery.createSpecifications();
    //分页
    Pageable pageable = new PageRequest(baseQuery.getCurrentPage(), baseQuery.getPageSize(), sort);
    //查询
    Page page = super.findAll(specs, pageable);
    return page;
    }

    @Override
    public List<T> findByQuery(BaseQuery baseQuery) {
    Sort sort = baseQuery.createSort();
    Specification spec = baseQuery.createSpecifications();
    //条件加排序查询
    List<T> list = super.findAll(spec, sort);
    return list;
    }

    @Override
    public List findByJpql(String jpql, Object... value) {
    Query query = entityManager.createQuery(jpql);
    for (int i = 0; i < value.length; i++) {
    query.setParameter(i+1, value[i]);
    }
    return query.getResultList();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    /**
    * BaseRepositoryFactoryBean --FactoryBean
    * JpaRepositoryFactoryBean --提供的FactoryBean
    * 写一个类去继承 JpaRepositoryFactoryBean --Spring就会自动调用createRepositoryFactory
    *
    */
    public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
    extends JpaRepositoryFactoryBean<T,S,ID> {

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
    return new MyRepositoryFactory<T,ID>(entityManager); //注:这里创建是我们的自定义类
    }

    //继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
    private static class MyRepositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory {
    private final EntityManager entityManager;
    /**
    * Creates a new {@link JpaRepositoryFactory}.
    *
    * @param entityManager must not be {@literal null}
    */
    public MyRepositoryFactory(EntityManager entityManager) {
    super(entityManager);
    this.entityManager = entityManager;
    }
    //这里返回最后的功能对象
    @Override
    protected Object getTargetRepository(RepositoryInformation information) {
    return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
    }
    //这里返回最后的功能对象 --最终Spring调用方法返回的对象 -->得到对最终的对象
    //factoryBean 默认调用getObject -- 现在调用getTargetRepository
    @Override
    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
    return BaseRepositoryImpl.class;
    }
    }
    }

    ​ 让Spring启动的时候,找BaseRepositoryImpl的实现 —>BaseRepositoryFactoryBean可以让spring去找

    BaseRepositoryImpl这个实现

    在applicationContext中增加

    1
    2
    3
    4
    5
    6
    7
    <!-- SpringDataJpa配置 -->
    <jpa:repositories base-package="cn.itsource.repository"
    transaction-manager-ref="transactionManager"
    entity-manager-factory-ref="entityManagerFactory"
    <!-- 加这一一个属性 -->
    factory-class="cn.itsource.repository.impl.BaseRepositoryFactoryBean"
    />

    2.抽取Service层

    创建一个公共接口 IBaseService –> 完成CRUD以及三个公共方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public interface IBaseService<T,ID extends Serializable> {
    //增加 修改
    void save(T t);
    //删除
    void del(ID id);
    //查询单个
    T findOne(ID id);
    //查询全部
    List<T> findAll();
    //分页排序查询
    Page findPageByQuery(BaseQuery baseQuery);
    //排序查询
    List<T> findByQuery(BaseQuery baseQuery);
    //jpql语句查询
    List jpqlByQuery(String jpql,Object...value);
    }

    创建一个实现类BaseServiceImpl —> 实现IBaseService —> 实现所有方法 完成所有方法 加上事务管理注解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    public class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T, ID> {

    @Autowired
    private BaseRepository<T,ID> baseRepository;

    @Override
    @Transactional
    public void save(T t) {
    baseRepository.save(t);
    }

    @Override
    @Transactional
    public void del(ID id) {
    baseRepository.delete(id);
    }

    @Override
    @Transactional
    public T findOne(ID id) {
    return baseRepository.findOne(id);
    }

    @Override
    public List<T> findAll() {
    return baseRepository.findAll();
    }

    @Override
    public Page findPageByQuery(BaseQuery baseQuery) {
    return baseRepository.findPageByQuery(baseQuery);
    }

    @Override
    public List<T> findByQuery(BaseQuery baseQuery) {
    return baseRepository.findByQuery(baseQuery);
    }

    @Override
    public List jpqlByQuery(String jpql, Object... value) {
    return baseRepository.findByJpql(jpql, value);
    }
    }

    ​ 再创建IEmployeeService和EmployeeServiceImpl 分别继承接口和实现类 —> 继承之后就具备了CRUD以及公共的查询方法了

    3.集成SpringMVC

    (1) 导包

    (2) 创建applicationContext-mvc配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!-- 对静态资源进行放行 -->
    <mvc:default-servlet-handler />
    <!-- 扫描controller部分的包 -->
    <!-- @Component组件, @Repository持久层, @Service业务逻辑层, and @Controller控制器 -->
    <context:component-scan base-package="cn.itsource.web" />
    <!-- 添加mvc对@RequestMapping等注解的支持 -->
    <mvc:annotation-driven />

    <!-- ViewResolver 视图解析器 (struts2视图类型类似) -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 设置视图路径的前后缀,该配置可以让我们写视图路径的时候更简单。 -->
    <!-- 希望跳转jsp是[/WEB-INF/views/前缀][xxx变量][.jsp后缀] -->
    <!-- * @see #setPrefix -->
    <property name="prefix" value="/WEB-INF/views/" />
    <!-- * @see #setSuffix -->
    <property name="suffix" value=".jsp" />
    </bean>

    <!-- 错误:提示告诉开发者你没有配置文件上传解析器。 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为1MB -->
    <property name="maxUploadSize">
    <value>1048576</value>
    </property>
    </bean>

    创建web.xml 进行配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <!-- 读取SpringMVC -->
    <context-param>
    <param-name>contextConfigLocation</param-name>
    大专栏  SpringDataJpa2"> <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 启动Spring的监听器 -->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 配置解决中文乱码的问题 -->
    <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置核心控制器-->
    <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <!-- 告诉SpringMVC到哪里去找配置文件 -->
    <param-name>contextConfigLocation</param-name>
    <!-- 注意:这里只读取springmvc的xml -->
    <param-value>classpath:applicationContext-mvc.xml</param-value>
    </init-param>
    <!-- Servlet默认在每一次访问的时候创建 -->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>

    后面需要自己配置tomcat

    4.加入Easyui

    把easyui的文件复制到web下边

    然后创建一个head.jsp 这个是专门方easyui引入的配置的

    因为很多页面需要用到 所以单独抽取出来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>

    <link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">

    <script type="text/javascript" src="/easyui/jquery.min.js"></script>
    <script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
    <script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
    <script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>
    <script type="text/javascript" src="/js/common.js"></script>
    1
    2
    3
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%-- 需要用到easyui引入 就加上这行代码 --%>
    <%@include file="/WEB-INF/views/head.jsp"%>

    然后就加入页面

    树形菜单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //获取左边树状菜单栏
    $("#menuTree").tree({
    //获取json中的数据
    url:"/json/menu.json",
    //点击事件
    onClick:function(node){
    //增加页签 把名字和地址传过去
    addTabs(node.text,node.url);
    }
    })

    就是上边树形菜单点击事件触发之后调用下面的函数增加页签

    tabs选项卡增加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function addTabs(text,url) {
    if(url){
    if(!$("#dataTab").tabs("exists",text)){
    var content = '<iframe scrolling="auto" frameborder="0" src="'+url+'" style="100%;height:100%;"></iframe>';
    $("#dataTab").tabs("add",{
    title:text,
    content:content,
    closable:true
    });
    }else{
    $("#dataTab").tabs("select",text);
    }
    }
    }

    5.分页

    因为json中分页需要total row

    1564844780728

    所以我们创建一个公共类

    类里面有这两个字段 rows是显示在页面的 数据 所以用List

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class UIPage {
    //总条数
    private Long total;
    //每页显示数据
    private List rows;

    public UIPage() {}

    public UIPage(Page page) {
    this.total = page.getTotalElements();
    this.rows = page.getContent();
    }
    //下面有get/set方法
    }

    在controller中 把分页查询出来的数据放到UIPage中去

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping("/page")
    @ResponseBody
    public UIPage page(EmployeeQuery employeeQuery){
    Page page = employeeService.findPageByQuery(employeeQuery);
    UIPage uiPage = new UIPage(page);
    return uiPage;
    }

    ​ 前台加载数据的时候 接受的参数用EmployeeQuery 但是需要在BaseQuery中设置set方法 把前台加载的页数和页面展示条数传到BaseQuery

    1
    2
    3
    4
    5
    6
    7
    8
    //因为前台传入的参数是page和rows
    public void setPage(Integer page){
    System.out.println(page);
    this.currentPage = page;
    }
    public void setRows(Integer rows){
    this.pageSize = rows;
    }

    前台传的参数

    1564845295829

    6.头像和部门

    在头像和部门的标签里加上 formatter (单元格formatter(格式化器)函数)

    1
    2
    <th width="20"  field="headImage" formatter="headImage" >头像</th>
    <th width="20" field="department" formatter="department" >部门</th>

    然后创建在js文件夹中创建一个model文件夹 里面创建一个employee的js文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function department(value) {
    if(value){
    return value.name;
    }
    }
    function headImage(value) {
    if(value){
    return "<img src='"+value+"' />";
    }
    }

    7.解决懒加载问题

    在wei.xml里面加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- 加上OpenEntityManager -->
    <filter>
    <filter-name>openEntity</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>openEntity</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    方法一:在实体类建立关系的上面加上注解

    1
    2
    3
    4
    @ManyToOne
    @JoinColumn(name = "department_id")
    @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
    private Department department;

    方法二:因为方法一只能对单个有效 有很多类都需要的时候 很麻烦

    ​ (1) 创建一个新的类(重写com.fasterxml.jackson.databind.ObjectMapper)

    1
    2
    3
    4
    5
    6
    7
    public class CustomMapper extends ObjectMapper {
    public CustomMapper(){
    this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    // 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false 对null的bean 不做序列化
    this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }
    }

    (2) 在applicationContext-mvc.xml中配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- 添加mvc对@RequestMapping等注解的支持 -->
    <mvc:annotation-driven >
    <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes">
    <list>
    <value>application/json; charset=UTF-8</value>
    <value>application/x-www-form-urlencoded; charset=UTF-8</value>
    </list>
    </property>
    <!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
    <property name="objectMapper">
    <!-- 这里路径根据自己的路径改 -->
    <bean class="cn.itsource.common.CustomMapper"></bean>
    </property>
    </bean>
    </mvc:message-converters>
    </mvc:annotation-driven>

    8.高级查询

    页面准备好之后 需要回显部门下拉框

    先去repositroy去写一个IDepartmentRepository接口

    再去service把IDepartmentService接口和实现类写好

    再创建一个UtilController

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Controller
    @RequestMapping("/util")
    public class UtilController {
    @Autowired
    private IDepartmentService departmentService;

    @RequestMapping("/departmentList")
    @ResponseBody
    public List<Department> departmentList(){
    List<Department> list = departmentService.findAll();
    return list;
    }
    }

    页面准备for表单 点击搜索的时候 加载数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $(function () {
    var searchForm = $("#searchForm");
    var employeeGrid = $("#employeeGrid");

    //获取带有data-method属性的a标签 然后绑定事件
    $("a[data-method]").on("click",function () {
    var methodName = $(this).data("method");
    itsource[methodName]();
    })

    var itsource = {
    search:function () {
    var parme = searchForm.serializeObject();
    employeeGrid.datagrid("load",parme);
    }
    }
    })

    在EmployeeQuery增加几个属性和条件

    1
    2
    3
    4
    5
    6
    7
    8
    public Specification createSpecifications() {
    Specification<Employee> specification = Specifications.<Employee>and()
    .like(StringUtils.isNotBlank(this.username), "username", "%" + this.username + "%")
    .like(StringUtils.isNotBlank(this.email), "email", "%" + this.email + "%")
    .eq(this.departmentId != null,"department.id",this.departmentId)
    .build();
    return specification;
    }
  • 相关阅读:
    python之安卓逆向HOOK系统通用类
    MySQL 排名、分组后组内排名、取各组的前几名
    MySQL case
    MySQL 行列相互转换
    MySQL学习笔记(四)
    回归分析
    构建决策树
    用K-Means聚类分析做客户分群
    会员数据化运营
    数据降维——主成分分析、因子分析、线性判别分析
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12360771.html
Copyright © 2011-2022 走看看