springboot+jpa 整合与基本应用

什么是jpa

JPA (The Java Persistence API)是用于访问,持久化和管理 Java 对象/类与关系型数据库之间的数据交互的 Java 规范。JPA 被定义为EJB (Enterprise JavaBeans) 3.0规范的一部分,作为 EJB 2 CMP 实体 Bean 规范的替代。

注意,JPA 只是一个标准,只定义了一系列接口,而没有具体的实现。很多企业级框架提供了对 JPA 的实现,如 Spring 。因此 Spring 本身与 JPA 无关,只是提供了对 JPA 的支持,因此在 Spring 中你也会看到很多注解都是属于 javax.persistence 包的。

JPA 允许 POJO(Plain Old Java Objects)轻松地持久化,而不需要类来实现 EJB 2 CM P规范所需的任何接口或方法。 JPA 还允许通过注解或 XML 定义对象的关系映射,定义 Java 类如何映射到关系数据库表。 JPA 还定义了一个运行时 EntityManager API,用于处理对象的查询和管理事务。 同时,JPA 定义了对象级查询语言 JPQL,以允许从数据库中查询对象,实现了对数据库的解耦合,提高了程序的可移植性,而不具体依赖某一底层数据库。

JPA 是 Java 持久化规范中的一个最新版本。第一个版本是 OMG 持久性服务 Java 绑定,但这个一个失败的产品,甚至没有任何商业产品支持它。接下来的版本是 EJB 1.0 CMP Entity Beans,它已经非常成功地被大型 Java EE 提供程序(BEA,IBM)采用,但是它复杂性太高而且性能比较差。EJB 2.0 CMP 试图通过引入本地接口来减少 Entity Bean 的一些复杂性,但是大多数复杂性仍然存在,而且缺乏可移植性。

历史总是要向前发展的,种种的这些使得 EJB 3.0 规范将降低复杂性作为主要目标,这导致规范委员会沿着 JPA 的路径前进。 JPA 旨在统一 EJB 2 CMP,JDO,Hibernate,从目前来看,JPA 的确取得了成功。

目前大多数持久化供应商已经发布了 JPA 的实现,并被行业和用户采用。这些包括 Hibernate(由 JBoss 和 Red Hat 收购),TopLink(由 Oracle 收购)和 Kodo JDO(由 BEA 和 Oracle 收购)。其他支持 JPA 的产品包括 Cocobase(由 Thought Inc. 收购)和 JPOX。

Spring Boot JPA - 基本使用

导入jar

在pom.xml中加入依赖

1    <dependency>
2            <groupId>org.springframework.boot</groupId>
3            <artifactId>spring-boot-starter-data-jpa</artifactId>
4    </dependency>
复制代码

创建实体

 1@Entity
 2public class User{
 3
 4
 5    @Id
 6    @GeneratedValue(strategy = GenerationType.IDENTITY)
 7    private Integer id;
 8
 9    private String phone;
10
11
12     public String getPhone() {
13        return phone;
14    }
15
16    public void setPhone(String phone) {
17        this.phone = phone;
18    }
19}
复制代码

Dao层接口

 1public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
 2
 3    User findByPhone(String phone);
 4
 5    User findByPhoneAndFlag(String phone, Integer flag);
 6
 7    User findByIdAndFlag(Integer userId, Integer flag);
 8
 9    User findByOpenIdAndFlag(String openId, Integer flag);
10
11    Page<User> findByFlag(Integer flag, Pageable pageable);
12
13    List<User> findByNewPersonAndFlagOrderByCreateTimeAsc(Integer isNewPerson, Integer flag);
14
15    User findById(Integer toBeFollowID);
16
17    List<User> findByFlagAndNewPerson(Integer flag, Integer isNewPerson, Pageable pageable);
18
19    List<User> findByNicenameIsLikeAndFlagAndNewPerson(String searchName, Integer flag, Integer isNewPerson, Pageable pageable);
20
21}
复制代码

spring data jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

 1        userDao.save(user);             //保存一个对象
 2        userDao.save(new List<User>);   //保存多个对象
 3        userDao.delete(user);           //删除一个对象
 4        userDao.delete(id);             //通过id删除
 5        userDao.deleteAll();            //删除所有
 6        userDao.delete(new ArrayList<>()); //批量删除
 7        userDao.findOne(id);        //通过id获取
 8        userDao.getOne(id);         //通过id获取    不推荐使用
 9        userDao.findAll(pageable);   //分页查找所有
10        userDao.exists(id);             //id是否存在
11        ......
复制代码

除此之外还提供了自定义方法名的方式查询(在userDao中)

1User findByOpenIdAndFlag(String openId, Integer flag);
2//等同于
3SELECT * FROM 'user' WHERE open_id =?1 AND flag = ?2
复制代码

具体的关键字,使用方法和生产成SQL如下表所示

KeywordSampleJPQL snippet
AndfindByLastnameAndFirstnamewhere x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstnamewhere x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEqualswhere x.firstname = 1?
BetweenfindByStartDateBetweenwhere x.startDate between 1? and ?2
LessThanfindByAgeLessThanwhere x.age < ?1
LessThanEqualfindByAgeLessThanEqualwhere x.age <= ?1
GreaterThanfindByAgeGreaterThanwhere x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqualwhere x.age >= ?1
AfterfindByStartDateAfterwhere x.startDate > ?1
BeforefindByStartDateBeforewhere x.startDate < ?1
IsNullfindByAgeIsNullwhere x.age is null
IsNotNull,NotNullfindByAge(Is)NotNullwhere x.age not null
LikefindByFirstnameLikewhere x.firstname like ?1
NotLikefindByFirstnameNotLikewhere x.firstname not like ?1
StartingWithfindByFirstnameStartingWithwhere x.firstname like ?1
EndingWithfindByFirstnameEndingWithwhere x.firstname like ?1
ContainingfindByFirstnameContainingwhere x.firstname like ?1
OrderByfindByAgeOrderByLastnameDescwhere x.age = ?1 order by x.lastname desc
NotfindByLastnameNotwhere x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> age)where x.age not in ?1
TruefindByActiveTrue()where x.active = true
FalsefindByActiveFalse()where x.active = false
IgnoreCasefindByFirstnameIgnoreCasewhere UPPER(x.firstame) = UPPER(?1)

分页查询

直接在controller层封装好Pageable对象即可

1@GetMapping("findBanners")
2public Page<Banner> findBanners(@PageableDefault(sort = {"priority"}, direction=Sort.Direction.ASC) Pageable pageable)
复制代码

==注意: #ad1f1f==
前端直接在请求的最后拼接上?page=0&size=10
如果前端不传page 和 size 这两个参数过来,那么@PageableDefault会默认为第1页开始,每页最大条数为10。需注意page为0时为第一页。
在service中调用即可

 1//返回给客户端的Page对象,其json格式为 
 2{ 
 3    "content": [],//数据内容 
 4    "first": true,//是否为第一页 
 5    "last": true,//是否为最后一页 
 6    "number": 0,//当前页码 
 7    "numberOfElements": 0,//当前页中的实际数据条数 
 8    "size": 0,//一页最大条数 
 9    "sort": { },//排序信息 
10    "totalElements": 0,//总条数 
11    "totalPages": 0//总页数 
12}
复制代码

自定义分页

1public Page<Banner> findBanners(int id){
2        int page = 1;
3        int size = 10;
4        Sort sort = new Sort(Sort.Direction.DESC,"priority");
5        Pageable pageable = new PageRequest(page,size,sort);
6        return bannserDao.findById(id,pageable);
7    }
复制代码

动态查询

1public Page<Admin> findAdminList(AdminCmsSearchVO adminCmsSearchVO, Pageable pageable) {
2        Specifications<Admin> spec = Specifications.where(commonSpecUtil.like("name", adminCmsSearchVO.getName()))
3                .and(commonSpecUtil.equal("clazzType", adminCmsSearchVO.getClazzType()))
4                .and(commonSpecUtil.equal("flag",ModelContants.AdminContant.FLAG_IS_TRUE));
5        return adminDao.findAll(spec, pageable);
6    }
复制代码
  1//(此代码由建东提供)
  2package com.luwei.common.utils;
  3
  4import org.springframework.data.jpa.domain.Specification;
  5import org.springframework.stereotype.Component;
  6
  7import java.util.Date;
  8import java.util.List;
  9
 10/**
 11 * Created by jdq on 2017/8/8.
 12 */
 13@Component
 14public class CommonSpecUtil<T> {
 15
 16    /**
 17     * 精确匹配(equal)
 18     *
 19     * @param srcName        字段名
 20     * @param targetProperty 匹配内容
 21     * @return
 22     */
 23    public Specification<T> equal(String srcName, Object targetProperty) {
 24        if (targetProperty == null) {
 25            return null;
 26        }
 27        return (root, query, cb) -> cb.equal(root.get(srcName), targetProperty);
 28    }
 29
 30    /**
 31     * 精确匹配(notEqual)
 32     *
 33     * @param srcName        字段名
 34     * @param targetProperty 匹配内容
 35     * @return
 36     */
 37    public Specification<T> notEqual(String srcName, Object targetProperty) {
 38        if (targetProperty == null) {
 39            return null;
 40        }
 41        return (root, query, cb) -> cb.notEqual(root.get(srcName), targetProperty);
 42    }
 43
 44    /**
 45     * 模糊匹配(like)
 46     *
 47     * @param srcName        字段名
 48     * @param targetProperty 匹配内容
 49     * @return
 50     */
 51    public Specification<T> like(String srcName, String targetProperty) {
 52        if (StringUtils.isEmpty(targetProperty)) {
 53            return null;
 54        }
 55        return (root, query, cb) -> cb.like(root.get(srcName), "%" + targetProperty + "%");
 56    }
 57
 58    /**
 59     * 日期范围匹配(timeBetween)
 60     *
 61     * @param srcName      字段名
 62     * @param startTimeStr 开始时间
 63     * @param endTimeStr   结束时间
 64     * @return
 65     */
 66    public Specification<T> timeBetween(String srcName, String startTimeStr, String endTimeStr) {
 67        Date startTime, endTime;
 68        if (StringUtils.isEmpty(startTimeStr)) {
 69            startTime = DateUtils.getDate2("1970-01-01 00:00:00");
 70        } else {
 71            startTime = DateUtils.getDate2(startTimeStr + " 00:00:00");
 72        }
 73
 74        if (StringUtils.isEmpty(endTimeStr)) {
 75            endTime = new Date();
 76        } else {
 77            endTime = DateUtils.getDate2(endTimeStr + " 23:59:59");
 78        }
 79        return (root, query, cb) -> cb.between(root.get(srcName), startTime, endTime);
 80    }
 81
 82    public Specification<T> parkingOrderTime(String srcName,String startTimeStr,String endTimeStr) {
 83        Date startTime,endTime;
 84        startTime=DateUtils.getDate2(DateUtils.tostartDayTime(startTimeStr));
 85        endTime = DateUtils.getDate2(DateUtils.toEndDayTime(endTimeStr));
 86
 87        return (root, query, cb) -> cb.between(root.get(srcName), startTime,endTime);
 88    }
 89
 90
 91    /**
 92     * 日期范围匹配(timeBetween)
 93     *
 94     * @param srcName   字段名
 95     * @param startTime 开始时间
 96     * @param endTime   结束时间
 97     * @return
 98     */
 99    public Specification<T> timeBetween(String srcName, Date startTime, Date endTime) {
100        if (org.springframework.util.StringUtils.isEmpty(startTime)) {
101            return null;
102        }
103        if (org.springframework.util.StringUtils.isEmpty(endTime)) {
104            return null;
105        }
106        return (root, query, cb) -> cb.between(root.get(srcName), startTime, endTime);
107    }
108
109    /**
110     * 数值范围匹配(between)
111     *
112     * @param srcName 字段名
113     * @param start   开始
114     * @param end     结束
115     * @return
116     */
117    public Specification<T> between(String srcName, Integer start, Integer end) {
118        if (org.springframework.util.StringUtils.isEmpty(start)) {
119            return null;
120        }
121        if (org.springframework.util.StringUtils.isEmpty(end)) {
122            return null;
123        }
124        return (root, query, cb) -> cb.between(root.get(srcName), start, end);
125    }
126
127    /**
128     * 大于等于(greaterThanOrEqualTo)
129     *
130     * @param srcName 字段名
131     * @param value   数值
132     * @return
133     */
134    public Specification<T> greaterThanOrEqualTo(String srcName, Integer value) {
135        if (org.springframework.util.StringUtils.isEmpty(value)) {
136            return null;
137        }
138        return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get(srcName), value);
139    }
140
141    /**
142     * 小于等于(lessThanOrEqualTo)
143     *
144     * @param srcName 字段名
145     * @param value   数值
146     * @return
147     */
148    public Specification<T> lessThanOrEqualTo(String srcName, Integer value) {
149        if (org.springframework.util.StringUtils.isEmpty(value)) {
150            return null;
151        }
152        return (root, query, cb) -> cb.lessThanOrEqualTo(root.get(srcName), value);
153    }
154
155    /**
156     * in条件帅选(in)
157     *
158     * @param srcName 字段名
159     * @param list    集合
160     * @return
161     */
162    public Specification<T> in(String srcName, List<Integer> list) {
163        if (org.springframework.util.StringUtils.isEmpty(list)) {
164            return null;
165        }
166        return (root, query, cb) -> cb.and(root.get(srcName).in(list));
167    }
168
169    /**
170     * 不为空(isNotNull)
171     *
172     * @param srcName 字段名
173     * @return
174     */
175    public Specification<T> isNotNull(String srcName) {
176        return (root, query, cb) -> cb.isNotNull(root.get(srcName));
177    }
178
179    /**
180     * 倒序(desc)
181     *
182     * @param srcName 字段名
183     * @return
184     */
185    public Specification<T> desc(String srcName) {
186        return (root, query, cb) -> query.orderBy(cb.desc(root.get(srcName).as(Integer.class))).getRestriction();
187    }
188
189    /**
190     * 升序(asc)
191     *
192     * @param srcName 字段名
193     * @return
194     */
195    public Specification<T> asc(String srcName) {
196        return (root, query, cb) -> query.orderBy(cb.asc(root.get(srcName).as(Integer.class))).getRestriction();
197    }
198
199}
复制代码

动态查找的条件:
1.adminDao要继承JpaSpecificationExecutor

enter description here

2.CommonSpecUtil提供了各种匹配的方法。如equals,like,notEqual……

参考博客

部分引用于袁荻的博客
原文地址


掘金segmentfaultV2EX知乎博客园开源中国github简书芦苇科技

广州芦苇科技Java开发团队

芦苇科技-广州专业软件外包服务公司

提供微信小程序、APP应用研发、UI设计等专业服务,专注于互联网产品咨询、品牌设计、技术研发等领域

访问 www.talkmoney.cn 了解更多

万能说明书 | 早起日记Lite | 凹凸壁纸 | 言财


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值