zoukankan      html  css  js  c++  java
  • Spring data JPA 理解(默认查询 自定义查询 分页查询)及no session 三种处理方法

    简介:Spring Data JPA 其实就是JDK方式(还有一种cglib的方式需要Class)的动态代理 (需要一个接口 有一大堆接口最上边的是Repository接口来自org.springframework.data.repository,
    还有CrudRepository接口及一个实现类SimpleJpaRepository),只要有接口就可以查询数据库了,实际上就是proxy的方法,具体查询的方法有两种
    一种是简单式就是方法名为findBy+属性名+(AndOrIsEquals等)
    另一种是自定义的方法就是属性名是瞎起的向abc xyz什么的根本找不到这个属性,这时就可以用sql或者jpql两种语言
    @Query(nativeQuery=false是默认的不用写,可以用jpql语言,value="from standard where name=?")
    @Query(nativeQuery=true必须写,代表用sql语言,value="select * from standard where c_name=?")
    public List<Standard> findByAbc(String name) 参数就是?
    如果是增删改操作还要加上@Modifying

    分页:对于分页查询,更是简便
    public interface StandardDao extends JpaRepository<Standard, Integer>{ //继承的接口中已经包含分页查询接口中的方法
    所以只需要在service的实现类中
    @Service
    @Transactional
    public class StandardServiceImpl implements StandardService { //调用dao接口中看不见的findAll()方法
    public Page<Standard> pageQuery(Pageable pageable) { 
    return standardDao.findAll(pageable);
    }
    这个PageAble也是个接口,他的实现类封装了page和rows两个浏览器提交过来的参数(发自easyui的datagrid的url请求,要求这个datagrid有pagination属性)
    Pageable pageable = new PageRequest(page-1, rows);
    注意page的索引是从0开始的,0表示第一页,所以要减一
    page是分页查询的页码 rows是每页几条
    在Web层的Action中只需要通过Spring框架自动注入Service接口的实现类对象
    @Autowired
    private StandardService standardService;
    调用其中方法
    Page<Standard> page = standardService.pageQuery(pageable);
    即可得到Page接口的实现类对象,
    page对象中的内容正是easyui的datagrid组件中必需的内容,但是名字不同不叫rows而是content
    {
    "total":86,
    "rows":[
    {"id":101,"name":"jack","age":20},
    {"id":102,"name":"rose","age":21},
    {"id":103,"name":"lili","age":22}
    ]
    }
    通过page.getTotalElements()获得总记录数"total"
    通过page.getContent()获得根据分页查询到内容
    通过输出到控制台
    System.out.println("总记录数:"+page.getTotalElements());
    System.out.println("当前页记录:"+page.getContent());
    发现结果分别是Number类型和List集合并不是我们需要的json格式
    通过Map集合转换为上边的json格式,把键值设置为我们需要的"rows"
    Map<String, Object> map = new HashMap<>();
    map.put("total", page.getTotalElements());
    map.put("rows", page.getContent());
    使用jsonlib的jsonObject转换成json字符串格式
    String json = JSONObject.fromObject(map).toString();
    发回浏览器
    ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
    ServletActionContext.getResponse().getWriter().write(json);

    保存:页面提交表单<form id="standardForm" action="${pageContext.request.contextPath}/standardAction_save.action" method="post">
    找到standardAction_save.action所指向的save方法
    用自动注入的service调用save方法
    standardService.save(model);
    在service的实现类中
    @Service
    @Transactional
    public class StandardServiceImpl implements StandardService {
    调用自动注入的dao
    @Autowired
    private StandardDao standardDao;
    的方法
    public void save(Standard model) {
    standardDao.save(model);
    }
    这个save(model)方法在dao的接口中看不到,在dao继承的接口CrudRepository中已经定义,增加修改都是save,没有add和update
    model来自实现ModelDriven接口
    implements ModelDriven<T>
    下边是向上抽取出的BaseAction父类
    public class BaseAction<T> extends ActionSupport implements ModelDriven<T> {

    protected T model;//这里需要new对象的,在构造方法中生成的
    public T getModel() {
    return model;
    }

    //子类action创建,父类无参构造执行,获取子类继承BaseAction中泛型Class
    /*
    * 参数化类型Type:BaseAction<Standard> -- cn.itcast.bos.web.action.common.BaseAction<cn.itcast.bos.base.Standard>
    * 实际类型参数:《》中class叫实际类型参数
    * */
    public BaseAction() {
    try {
    //第一步:获取当前运行class-子类
    Class clzz = this.getClass();
    System.err.println(clzz);
    //第二步:获取子类继承父类的class--参数化类型
    /*Type getGenericSuperclass() Type:接口 Class是Type实现类
    返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。 */
    Type type = clzz.getGenericSuperclass();
    System.err.println(type);
    //将Type接口转为子接口 ParameterizedType
    ParameterizedType parameterizedType = (ParameterizedType) type;
    //第三步:获取实际类型参数-model对象class
    Type[] types = parameterizedType.getActualTypeArguments(); //[cn.itcast.bos.base.Standard]
    System.err.println(types);
    //将Type接口转为实现类Class
    Class clzzzzzzzzzzzz = (Class) types[0];
    //第四步:将class实例化
    model = (T) clzzzzzzzzzzzz.newInstance();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    //通过属性驱动获取当前页,每页显示记录数
    //page-1
    protected Integer page;
    protected Integer rows;
    public void setPage(Integer page) {
    this.page = page-1;
    }


    public void setRows(Integer rows) {
    this.rows = rows;
    }

    /**
    * @Description: 将service中查询到Page对象转为分页需要json数据
    * @param page
    * @param excluds
    *
    */
    public void java2Json(Page<T> page, String[] excluds){
    try {
    Map<String, Object> map = new HashMap<>();
    map.put("total", page.getTotalElements());
    map.put("rows", page.getContent());

    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.setExcludes(excluds);

    String json = JSONObject.fromObject(map, jsonConfig).toString();
    System.err.println(json);
    ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
    ServletActionContext.getResponse().getWriter().write(json);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**
    * @Description: 将List集合转为json数组
    */
    public void java2Json(List list , String[] excluds){
    try {
    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.setExcludes(excluds);
    String json = JSONArray.fromObject(list, jsonConfig).toString();
    System.err.println(json);
    ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
    ServletActionContext.getResponse().getWriter().write(json);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    关于no session问题
    下边在分页查询快递员时,如果不处理courier实体中外键关联的集合采用懒加载方式而导致no session异常,也就是
    Page<Courier> page = courierService.pageQuery(model, pageable);执行后已经查询出快递员,但在转json的时候,
    session已经关了,懒加载的集合没有session无法加载
    解决方法一,
    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.setExcludes(new String[]{"fixedAreas", "company"});
    忽略掉fixedAreas集合就可以了,不用它

    相关代码如下:
    @Action("courierAction_pageQuery")
    public String pageQuery() throws Exception {
    Pageable pageable = new PageRequest(page, rows);
    Page<Courier> page = courierService.pageQuery(model, pageable);
    this.java2Json(page, new String[]{"fixedAreas"});
    /*Map<String, Object> map = new HashMap<>();
    map.put("total", page.getTotalElements());
    map.put("rows", page.getContent());

    //将快递员对象中集合属性fixedAreas排除掉(忽略该属性,最终在快递员对象不存在属性)
    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.setExcludes(new String[]{"fixedAreas", "company"});

    String json = JSONObject.fromObject(map, jsonConfig).toString();
    System.err.println(json);
    ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
    ServletActionContext.getResponse().getWriter().write(json);*/
    return NONE;
    }
    解决方法二,
    也可以将session(Spring data JPA中是EntityManager)延长至web层

    <filter>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>


    解决方法三

    @ManyToMany(fetch=FetchType.EAGER, mappedBy = "couriers")//jpa默认策略 集合形式延迟加载
    private Set<FixedArea> fixedAreas = new HashSet<FixedArea>();

  • 相关阅读:
    windows下安装rabbitmq
    selectors
    修改Docker默认镜像和容器的存储位置
    eclipse配置jdk的src.zip源代码步骤
    Zookeeper WINDOWS 安装配置
    zookeeper windows 入门安装和测试
    zookeeper集群搭建(windows环境下)
    ant使用指南详细入门教程
    linux查看系统版本和系统位数
    suse linux 命令
  • 原文地址:https://www.cnblogs.com/qingyundian/p/9231830.html
Copyright © 2011-2022 走看看