我是靠谱客的博主 悲凉跳跳糖,最近开发中收集的这篇文章主要介绍JPA -- 表关系映射 || 增删改查 || 一个方法实现分页+排序+动态条件查询,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

entity 表关系

基础注解

@JsonIgnore     将不需要返回的属性上添加忽略,多为复杂表关系属性排除使用
@Transient      表明为成员变量,不和数据库字段做映射

@Id                         表明为主键,定义与Id上
@Table(name = "ws_user")    类名与数据库表名的关系映射,定义与类上
@Entity                     表明为实体类,定义与类上

配置里面如果定义了jpa 为 update,会自动建表,@Transient 注解的字段不会被创建
--------1、数据库不存在表会自动创建表
--------2、数据库不存在某些字段数据库会自动创建该字段
--------3、指定了外键关系会自动在数据库中生成外键


@DynamicInsert
--------设置为true,设置为true,表示insert对象的时候,生成动态的insert语句,
--------如果这个字段的值是null就不会加入到insert语句当中.默认false。
--------比如希望数据库插入日期或时间戳字段时,在对象字段为空的情况下,表字段能自动填写当前的sysdate。

@DynamicUpdate
--------设置为true,设置为true,表示update对象的时候,生成动态的update语句,
--------如果这个字段的值是null就不会被加入到update语句中,默认false。

表关系注解

@OneToOne       一对一
@OneToMany      一对多
@ManyToOne      多对一
@ManyToMany     多对多


表关系注解属性详细说明

----- cascade: 表示默认的级联操作策略,可以指定为ALL(全部),默认为无级联操作
      -------- ALL    (下方全部)@ManyToMany(cascade=CascadeType.ALL)
      -------- PERSIST(级联保存),
      -------- MERGE  (级联更新),
      -------- REFRESH(级联刷新)
      -------- REMOVE (级联删除)
      
----- fetch:  表示抓取策略,默认为 ,
      -------- EAGER(急记载,立即记载)-->  默认:FetchType.EAGER
      -------- LAZY (懒加载)
      
----- optional: 表示否允许该字段为null,该属性应该根据数据库表的外键约束来确定
      -------- true     默认
      -------- false  

@Column 字段映射注解

@Column  注解属性说明,指定生成的表字段名和长度,不指定默认255长度且表字段名同属性名一致

------ 特殊字段关系映射示例,如 desc等mysql 关键字
         @Column(name = "`desc`")
         private String desc;
      
------ 指定字段 tradeNo 长度为50,且值不能为null 示例
        @Column(name = "tradeNo", length = 50, nullable = false)
 
------ 指定字段 tradeNo 长度为50,且值可以为null 示例
        @Column(name = "tradeNo", length = 50, nullable = true)
 
------ 指定字段totalAmount(长度)为10,小数点位数为2位,且值不能为null 示例
        @Column(name = "totalAmount", precision = 10, scale = 2, nullable = false)

@GeneratedValue 主键策略注解

@GeneratedValue  主键策略, 定义与id字段处  
      示例: @GeneratedValue(strategy=GenerationType.AUTO)  
      
     ------IDENTITY: 采用数据库ID自增长的方式来自增主键字段,Oracle 不支持这种方式; 
     ------AUTO:     JPA自动选择合适的策略,是默认选项; 
     ------SEQUENCE: 通过序列产生主键,通过@SequenceGenerator 注解指定序列名,MySql不支持这种方式 
     ------TABLE:    通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

User 用户类 (具体表关系配置如下)


@Entity                   // 该注解声明一个实体类,与数据库中的表对应
@Table(name = "ws_user")  //生成数据库的表名
public class User {

    @Id                   //  表明主键id
    @GeneratedValue       //  主键的生成策略(看最下方注释具体说明)
    private Long userId;

    private String username;

    private String password;


    //======================= 用户 - [ 一对一 ] - 用户详情 ================

    // @JoinColumn(name = "user_id")      //外键关联
    @PrimaryKeyJoinColumn                 //主键关联
    @OneToOne(cascade=CascadeType.ALL)    //ALL 级联/添加/更新/删除(看最下方注释具体说明)
    // 用户详情类
    private UserDetail detail;           


    //======================= 用户 - [ 一对多 ] - 收获地址 ===============

    //外键关联,指定一的一端的id 做外键
    @JoinColumn(name = "user_id")
    @OneToMany(cascade=CascadeType.ALL)
    // 地址类
    private List<Address> addresses;


    //======================= 用户 - [ 多对一 ] - 部门  ================

    //外键关联,指定一的一端的id 做外键
    @JoinColumn(name = "dep_id")
    @ManyToOne(cascade=CascadeType.ALL)
     // 部门类
    private Dep dep;

 
   //======================= 用户 - [ 多对多 ] - 角色 ===================
    
    //name指中间表的表名,joinColumns指当前实体在中间表的字段,inverserJoinCloumns指关联的另外一个实体在中间表的字段名
    @JoinTable(name="ws_user_role",joinColumns=@JoinColumn(name="user_id"),inverseJoinColumns=@JoinColumn(name="role_id"))
    @ManyToMany(cascade=CascadeType.ALL)
    //角色类
    private List<Role> roles;
 
  set,get 方法自行添加........
 

dao层详解

package ws.cn.jpa.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Component;
import ws.cn.jpa.entity.User;

/**
 * Created by Administrator on 2018/10/2/002.
 * JpaRepository<User,Long> 说明:
 * User 实体类
 * Long 实体类主建的数据类型
 */

@Component
public interface UserDao extends JpaRepository<User,Long>,JpaSpecificationExecutor<User> {

    //自定义 sql 语句(语法一)
    @Query(value = "SELECT * FROM USER WHERE id = ?1", nativeQuery = true)
    User selectId(Integer id);

/*
 * 我们在这里直接继承 JpaRepository,CrudRepository,PagingAndSortingRepository,JpaSpecificationExecutor
 * 这里面已经有很多现成的方法
 * 这也是JPA的一大优点
 *
 *  (1) CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法
 *  (2) PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法
 *  (3)JpaRepository: 继承 PagingAndSortingRepository,实现一组 JPA 规范相关的方法
 *  (4)JpaSpecificationExecutor: 实现条件查询
 *
 *   注解说明
 *   @Query: 自定义sql , 接口方法上使用
 *   @Modifying : 接口方法上如涉及到删除和修改在需要加上@Modifying
 *   @Transactional : 也可以根据需要添加 @Transactional 对事物的支持,查询超时的设置等
 */
}

传值语法二:及修改删除示例

/**
	 * 修改
	 * @return
	 */
	@Transactional
	@Modifying(clearAutomatically = true)
	@Query(value = "UPDATE Hero hero SET hero.equip=:equip WHERE hero.id= :id and hero.uid = :uid ")
	int upd(@Param("id") long id, @Param("uid") long uid, @Param("equip") String equip);
	
	
	/**
	 * 删除
	 * 
	 */
	@Modifying
	@Transactional
	@Query(value="delete from Hero e where uid=:uid and e.id in (:ids)")
	int deleteByIds(@Param("uid")long uid,@Param("ids")List<Long> ids);

数据操作详解

直接controller 层测试了
此处直接调用的 dao 层,请自行把复杂代码防止 service层在用 contrller 层调用

package ws.cn.jpa.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import ws.cn.jpa.dao.UserDao;
import ws.cn.jpa.entity.User;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/10/2/002.
 */
@RestController
public class UserController {
  
    @Autowired
    private UserDao userDao;

    //============查询所有===============
    @GetMapping("/listuser")
    public List<User> findAll() {
        // Sort  第一个属性为排序规则, 第二个属性为按照那个字段来排序
        Sort sort = new Sort(Sort.Direction.DESC, "userId");
        //findAll() 可以不带sort属性,默认排序
        return userDao.findAll(sort);
    }


    //============ id 查询===============
    @GetMapping("/findById")
    public User findById(Long id) {
        id = 3L;   //模拟 id
        User user = userDao.findById(Long.valueOf(id)).get();
        return user;
    }


    //============ 多id 查询===============
    @GetMapping("/findAllById")
    public List findAllById(List<Long> ids) {
        // 模拟 id
        List list = new ArrayList();
        list.add(Long.valueOf(2));
        list.add(Long.valueOf(3));
        List users = userDao.findAllById(list);
        return users;
    }


    //============ 分页查询===============
    @GetMapping("/pageuser")
    public Page<User> pageuser() {
        // 开始页数 / 每页数量 / 排序规则 / 根据id排序
        Pageable pageable = new PageRequest(0, 2, Sort.Direction.DESC, "id");
        Page<User> page = userDao.findAll(pageable);
       
        System.out.println(page.getTotalElements() + "-->总数据数"+"/r/n"+
                page.getTotalPages() + "-->总页数"+"/r/n"+
                page.getNumber() + "-->当前页"+"/r/n"+
                page.getSize() + "-->每页条数"+"/r/n"+
                page.getNumberOfElements() + "-->本页条数"+"/r/n"+
                "查询到的数据:" + page.getContent()
        );
        
        return page;
    }


    //============ 动态条件查询 ===============
    /*
     *  username = 666 and  password = 666
     *  username = 666 or   password = 666
     **/
    @GetMapping("/queryStudent")
    public List<User> queryStudent(User user) {
        user.setUsername("666");
        user.setPassword("666");
        //生成条件
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                // and 条件
                List<Predicate> ands = new ArrayList<>();
                if (user.getUsername() != null && !"".equals(user.getUsername())) {
                    ands.add(criteriaBuilder.equal(root.<String>get("username"), user.getUsername()));
                }
                if (user.getUsername() != null && !"".equals(user.getUsername())) {
                    ands.add(criteriaBuilder.equal(root.<String>get("password"), user.getPassword()));
                }
                // or 条件
                List<Predicate> ors = new ArrayList<>();
                ors.add(criteriaBuilder.like(root.<String>get("username"), "%"+"9"+"%")); //模糊查询 like
                ors.add(criteriaBuilder.like(root.<String>get("password"), "%"+"9"+"%")); //模糊查询 like

                Predicate and = criteriaBuilder.and(ands.toArray(new Predicate[ands.size()])); //and 连接的条件集
                Predicate or = criteriaBuilder.or(ors.toArray(new Predicate[ors.size()]));     //or 连接的条件集

                List<Predicate> predicate = new ArrayList<>(); //条件集集合
                predicate.add(and); //添加 and 的条件集
                predicate.add(or);  //添加 or 的条件集

                //return criteriaBuilder.and(predicate.toArray(new Predicate[predicate.size()]));// and 连接条件集
                return criteriaBuilder.or(predicate.toArray(new Predicate[predicate.size()]));  // or  连接条件集
            }
        };
        List userDaoAll = userDao.findAll(specification);
        return userDaoAll;
    }


    //============ 添加、修改数据===============
    @GetMapping("/adduser")
    public void addUser(User user) {
        userDao.save(user);
    }


    //============ 添加多条数据===============
    @GetMapping("/saveAll")
    public void saveAll() {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User user = new User("mm" + i, "123456");
            list.add(user);
        }
        //保存实体集合
        userDao.saveAll(list);
    }


    //============ id 删除数据===============
    @GetMapping("/deleteId")
    public void deleteuser(Long id) {
        userDao.deleteById(id);
    }
    

    //============ 多 id 删除数据===============
    @GetMapping("/deleteIds")
    public void deleteAll(List<Long> ids) {
        List list = new ArrayList();
        list.add(Long.valueOf(7));
        list.add(Long.valueOf(8));
        list.add(Long.valueOf(9));
        userDao.deleteAll(list);
    }


    //============ 删除所有数据 ===============
    @GetMapping("/deleteAll")
    public void deleteAll(Long id) {
        userDao.deleteAll();
    }
}

一个方法实现分页+排序+动态条件查询

动态查询大致 API 一览

 
And             并且
Or              或
Is,Equals       等于

Between         两者之间
LessThan       小于
LessThanEqual     小于等于
GreaterThan      大于
GreaterThanEqual   大于等于

After            之后(时间) >
Before            之前(时间) <
IsNull         等于Null
IsNotNull,NotNull  不等于Null

Like              模糊查询。查询件中需要自己加 %
NotLike              不在模糊范围内。查询件中需要自己加 %

StartingWith       以某开头
EndingWith         以某结束
Containing        包含某

OrderBy            排序
Not              不等于
In                某范围内
NotIn              某范围外
True              真
False             假
IgnoreCase         忽略大小写

添加分页方法接口–dao层

@Override
Page<User> findAll(Specification<User> spec, Pageable pageable);

service 层添加

排序字段 : Sort.Direction.DESC, “id”) ,可以定义到controller 层
param : 查询参数
jpa包路径:import org.springframework.data.domain. (别引错)

/**
* @param  page  页数
* @param  size  记录数
* @param  param  查询条件
*/
public Page<User> Page(int page,int size,Map<String, Object> param)
	{
		return dao.userDao.findAll(new Specification<User>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// TODO Auto-generated method stub
				List<Predicate> list = new ArrayList<>();
				// 查询条件拼接
				for (String key : param.keySet()) {
					  list.add(cb.like(root.get(key).as(String.class), ("%"+param.get(key)+"%").toString()));
				}
				Predicate[] p = list.toArray(new Predicate[0]);
				return cb.and(p);
			}

		},PageRequest.of(page-1, size,Sort.Direction.DESC, "id"));
	}

controller

	/**
	 * 分页查询
	 * 
	 * @return
	 */
	@RequestMapping("/user")
	String list() {
		// 查询条件
		Map<String, Object> param = new HashMap<String, Object>(8);
		param.put("name", "张三");
		param.put("account", getString("account","666"));
		// 查询
		Page<User> page = service.userService.Page(1,20,param), 
	}

查询条件拼接 / 部分示例如下(精准/模糊/ 时间)

具体看api

      for (String key : param.keySet()) { }    遍历拼接每一个参数
      
      //模糊查询
	  list.add(cb.eq(root.get(key).as(String.class), ("%"+param.get(key)+"%").toString()));
    
      //精准查询
     //list.add(cb.equal(root.get(key).as(String.class), (param.get(key)).toString()));
   
     //时间段查询
    // list.add(cb.between(root.get("time"), mapTime.get("startTime"), mapTime.get("overTime")));
     	
     //大于或等于传入时间
    // list.add(cb.greaterThanOrEqualTo(root.get("commitTime").as(String.class), stime));

    // 小于或等于传入时间
    // list.add(cb.lessThanOrEqualTo(root.get("commitTime").as(String.class), etime));
     

最后

以上就是悲凉跳跳糖为你收集整理的JPA -- 表关系映射 || 增删改查 || 一个方法实现分页+排序+动态条件查询的全部内容,希望文章能够帮你解决JPA -- 表关系映射 || 增删改查 || 一个方法实现分页+排序+动态条件查询所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部