介绍
<a name="B7oCq"></a>
# 前置操作
<a name="J8crA"></a>
## ✨主要就是配置数据库的连接,这是常规操作
> **如果要自定建库 ,请参考** [自动建库](https://www.yuque.com/tanning/yg9ipo/os495n?view=doc_embed)
```yaml
server.port=1238
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.datasource.password=root
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://192.168.0.3:3306/hjpa?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
数据初始化(测试项目)
INSERT INTO `hjpa`.`sys_user`(`id`, `create_time`, `create_user_name`, `update_time`, `update_user_name`, `address`, `login_name`, `login_pwd`, `name`, `phone`, `user_icon`, `user_no`) VALUES (1, '2021-11-17 11:08:38', 'admin', '2021-12-03 14:02:22', 'admin', '重庆s', 'admin', '123', '超级管理员', '15888888888', NULL, 'admin');
INSERT INTO `hjpa`.`sys_user`(`id`, `create_time`, `create_user_name`, `update_time`, `update_user_name`, `address`, `login_name`, `login_pwd`, `name`, `phone`, `user_icon`, `user_no`) VALUES (2, '2021-12-03 13:48:14', 'admin', '2021-12-03 13:50:01', 'admin', '', 'user', '123', '用户1', '231', NULL, '1466645430750781440');
INSERT INTO `hjpa`.`sys_user`(`id`, `create_time`, `create_user_name`, `update_time`, `update_user_name`, `address`, `login_name`, `login_pwd`, `name`, `phone`, `user_icon`, `user_no`) VALUES (3, '2021-12-03 14:05:23', 'admin', '2021-12-03 14:05:43', 'admin', '', 'user02', '123', '用户2', '12321', NULL, '1466649744075108352');
INSERT INTO `hjpa`.`sys_user`(`id`, `create_time`, `create_user_name`, `update_time`, `update_user_name`, `address`, `login_name`, `login_pwd`, `name`, `phone`, `user_icon`, `user_no`) VALUES (4, '2021-12-10 15:02:39', 'admin', '2021-12-10 15:02:39', 'admin', '', 'SH-01', '123', '111', '', NULL, '1469200870634397696');
INSERT INTO `hjpa`.`sys_user`(`id`, `create_time`, `create_user_name`, `update_time`, `update_user_name`, `address`, `login_name`, `login_pwd`, `name`, `phone`, `user_icon`, `user_no`) VALUES (5, '2021-12-10 15:02:49', 'admin', '2021-12-10 15:03:00', 'admin', '222', 'LR-01', '1231', '111', '1312', NULL, '1469200914007695360');
全局异常处理
全局异常捕获
基础配置
实体继承JpaAuditFields可选
如果不使用基础字段,一定要继承
SerializableVO
,因为有些功能用到了里面的内置方法
package cn.tannn.hjpa.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/**
* 用户表
* @author : tn
* @date : 2021-9-10
*/
@Entity
@Table(name = "sys_user",
indexes = {
@Index(name = "user_no_index", columnList = "userNo", unique = true),
})
@org.hibernate.annotations.Table(appliesTo = "sys_user", comment = "用户表")
@Data
@EqualsAndHashCode(callSuper = true)
@DynamicUpdate
@DynamicInsert
public class User extends JpaAuditFields<User> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition="int(11) COMMENT '主键,自动生成'")
private Integer id;
/**
* 用户编号
*/
@Column(columnDefinition = " varchar(50) not null comment ' 用户编号' ")
private String userNo;
/**
* 姓名
*/
@Column(columnDefinition = " varchar(100) not null comment ' 姓名' ")
private String name;
/**
* 地址
*/
@Column(columnDefinition = " varchar(100) comment ' 地址' ")
private String address;
/**
* 登录名称
*/
@Column(columnDefinition = " varchar(100) not null comment '登录名称' ")
private String loginName;
/**
* 登录密码
*/
@Column(columnDefinition = " varchar(100) not null comment '登录密码' ")
private String loginPwd;
/**
* 手机号/联系电话
*/
@Column(columnDefinition = " varchar(15) comment ' 手机号/联系电话 ' ")
private String phone;
/**
* 用户头像
*/
@Column(columnDefinition = " varchar(60) comment ' 用户头像' ")
private String userIcon;
}
Repository继承JpaBasicsDao
如果实体不使用基础字段,一定要继承
SerializableVO
,因为有些功能用到了里面的内置方法
package cn.tannn.hjpa.dao;
import cn.jdevelops.jpa.server.dao.JpaBasicsDao;
import cn.tannn.hjpa.entity.User;
/**
* 用户表
*
* @author tan
* @date 2021-09-10 1StudentDao1:08
*/
public interface UserDao extends JpaBasicsDao<User, Integer> {
}
Service 继承 J2Service
有个
JService
也可以用,但是后期可能会被删除
package cn.tannn.hjpa.service;
import cn.jdevelops.jpa.server.service.J2Service;
import cn.tannn.hjpa.entity.User;
/**
* 用户表
*
* @author lxw
* @className 用户表
* @date 2021-09-10 11:24
*/
public interface UserService extends J2Service<User> {
}
ServiceImpl 继承 J2ServiceImpl
service 使用的是
J2Service
则 实现就必须继承J2ServiceImpl
package cn.tannn.hjpa.service.impl;
import cn.jdevelops.jpa.server.service.impl.J2ServiceImpl;
import cn.tannn.hjpa.dao.UserDao;
import cn.tannn.hjpa.entity.User;
import cn.tannn.hjpa.service.UserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 用户表
*
* @author lxw
* @className * 用户表
* @date 2021-09-10 11:41
*/
@Slf4j
@Service
public class UserServiceImpl extends J2ServiceImpl<UserDao, User, Integer> implements UserService {
}
使用演示
自带的方法基本都一看都懂,我这儿演示下动态查询个 service中 直接使用 Repository
- 细节情况本文档的下层文档
JPAUtilExpandCriteria 查询
@Autowired
private UserService userService;
@PostMapping("dyFind")
public ResultVO<List<UserVO>> dyFind(UserFindDTO user){
User to = user.to(User.class);
JPAUtilExpandCriteria<User> selectBean = CommUtils.getSelectBean(to);
List<User> all = userService.getJpaBasicsDao().findAll(selectBean);
return ResultVO.successForData(User.to(all, UserVO.class));
}
简单使用
调用接口:Post : http://127.0.0.1:8080/dyFind
curl —location —request POST ‘http://127.0.0.1:8080/dyFind‘ —header ‘Content-Type: application/json’ —data-raw ‘{}’
不存参数
查询所有
Hibernate: select user0_.id as id1_0_, user0_.create_time as create_t2_0_, user0_.create_user_name as create_u3_0_, user0_.update_time as update_t4_0_, user0_.update_user_name as update_u5_0_, user0_.address as address6_0_, user0_.login_name as login_na7_0_, user0_.login_pwd as login_pw8_0_, user0_.name as name9_0_, user0_.phone as phone10_0_, user0_.user_icon as user_ic11_0_, user0_.user_no as user_no12_0_ from sys_user user0_ where 1=1
选择传入
默认 and and 相连
Hibernate: select user0_.id as id1_0_, user0_.create_time as create_t2_0_, user0_.create_user_name as create_u3_0_, user0_.update_time as update_t4_0_, user0_.update_user_name as update_u5_0_, user0_.address as address6_0_, user0_.login_name as login_na7_0_, user0_.login_pwd as login_pw8_0_, user0_.name as name9_0_, user0_.phone as phone10_0_, user0_.user_icon as user_ic11_0_, user0_.user_no as user_no12_0_ from sys_user user0_ where user0_.address=? and user0_.phone=?
高阶使用
设置条件的 连接符 和 运算符
- 在实体中加入
@JpaSelectOperator_(_operator = SQLOperator._EQ_,ignoreNull = true, connect = SQLConnect._AND)_
- 详情请看注解注释’
- 传参测试
{
"name": "超",
"userNo": "146664"
}
SELECT
user0_.id AS id1_0_,
user0_.create_time AS create_t2_0_,
user0_.create_user_name AS create_u3_0_,
user0_.update_time AS update_t4_0_,
user0_.update_user_name AS update_u5_0_,
user0_.address AS address6_0_,
user0_.login_name AS login_na7_0_,
user0_.login_pwd AS login_pw8_0_,
user0_.NAME AS name9_0_,
user0_.phone AS phone10_0_,
user0_.user_icon AS user_ic11_0_,
user0_.user_no AS user_no12_0_
FROM
sys_user user0_
WHERE
user0_.address =?
AND user0_.phone =? Hibernate : SELECT
user0_.id AS id1_0_,
user0_.create_time AS create_t2_0_,
user0_.create_user_name AS create_u3_0_,
user0_.update_time AS update_t4_0_,
user0_.update_user_name AS update_u5_0_,
user0_.address AS address6_0_,
user0_.login_name AS login_na7_0_,
user0_.login_pwd AS login_pw8_0_,
user0_.NAME AS name9_0_,
user0_.phone AS phone10_0_,
user0_.user_icon AS user_ic11_0_,
user0_.user_no AS user_no12_0_
FROM
sys_user user0_
WHERE
user0_.user_no LIKE ?
OR user0_.NAME LIKE ?
SpecificationUtil 查询
只写了个简单的测试用例,具体使用,等项目中用到了再来补充
HjpaApplicationTests(示例项目中测试类)
package cn.tannn.hjpa;
import cn.jdevelops.jap.core.util.JPAUtilExpandCriteria;
import cn.jdevelops.jap.core.util.SpecificationUtil;
import cn.jdevelops.jap.core.util.criteria.Restrictions;
import cn.tannn.hjpa.entity.User;
import cn.tannn.hjpa.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
@Transactional(rollbackFor = Exception.class)
class HjpaApplicationTests {
@Autowired
private UserService userService;
@Test
void testSpecificationUtil() {
/**
*
WHERE
( address LIKE '%重庆%' )
AND (
NAME = '用户'
OR login_pwd = '123'
OR phone = '123'
OR user_no = '123')
*/
// address().and(
// name().or(loginPwd()).or(phone()).or(userNo())
// )
SpecificationUtil<User> instance = SpecificationUtil.getInstance();
Specification<User> and = instance.like("address", "重庆", true)
.and(instance.eq("name", "用户", true)
.or(instance.eq("loginPwd", "123", true))
.or(instance.eq("phone", "123", true))
.or(instance.eq("userNo", "123", true))
);
userService.getJpaBasicsDao().findAll(and).forEach(System.out::println);
}
@Test
void testAndOr1() {
/**
* WHERE
* ( address LIKE '重庆' )
* AND (
* NAME LIKE '%用户%'
* OR login_pwd LIKE '123'
* OR phone LIKE '123'
* OR phone LIKE '123'
* )
*/
userService.getJpaBasicsDao().findAll(
address().and(name().or(loginPwd()).or(phone()).or(userNo()) )
).forEach(System.out::println);
}
@Test
void testAndOr2() {
userService.getJpaBasicsDao().findAll(
address().and(
loginPwd().or(phone()).or(name())
).or(
loginPwd().and(
phone().or(name())
)
)
).forEach(System.out::println);
}
@Test
void test3() {
Specification<User> test = (root, criteriaQuery, criteriaBuilder) -> criteriaQuery.getRestriction();;
userService.getJpaBasicsDao().findAll(test).forEach(System.out::println);
}
public static Specification<User> name() {
return (root, query, builder) -> builder.like(root.get("name"), "%用户%");
}
public static Specification<User> loginPwd() {
return (root, query, builder) -> builder.like(root.get("loginPwd"), "123");
}
public static Specification<User> address() {
return (root, query, builder) -> builder.like(root.get("address"), "重庆");
}
public static Specification<User> phone() {
return (root, query, builder) -> builder.like(root.get("phone"), "123");
}
public static Specification<User> userNo() {
return (root, query, builder) -> builder.like(root.get("phone"), "123");
}
}
其他
SerializableVO
实体互转方法to JpaExample to = jpaExampleVo.to(JpaExample.class);
- to(list, Bvo.Class) List转List
- to(b, Bvo.Class) B转Bvo
- to(Page, Bvo.Class) JPA的Page转 Page
-
JpaAuditFields
/**
* 表示该字段为创建时间字段,在这个实体被insert的时候,会自动为其赋值
*/
@ApiModelProperty(value = "创建时间",hidden=true)
private LocalDateTime createTime;
/**
* 表示该字段为创建人,在这个实体被insert的时候,会自动为其赋值
*/
@ApiModelProperty(value = "创建人",hidden=true)
private String createUserName;
/**
* 表示该字段为修改时间字段,在这个实体被update的时候,会自动为其赋值
*/
@ApiModelProperty(value = "修改时间",hidden=true)
private LocalDateTime updateTime;
/**
* 表示该字段为修改人,在这个实体被update的时候,会自动为其赋值
*/
@ApiModelProperty(value = "修改人",hidden=true)
private String updateUserName;
JPA的预处理使用的MySQL版本选择测试
示例项目地址