首页
归档
留言
广告合作
友链
美女主播
Search
1
博瑞GE车机升级/降级
5,146 阅读
2
Mac打印机设置黑白打印
4,517 阅读
3
修改elementUI中el-table树形结构图标
4,516 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,351 阅读
5
intelliJ Idea 2022.2.X破解
4,060 阅读
Java
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Spring Cloud
Mac
mybatis
WordPress
Nacos
Spring Cloud Alibaba
Mybatis-Plus
jQuery
Java Script
asp.net
微信小程序
Sentinel
UniApp
MySQL
asp.net core
IntelliJ IDEA
Jpa
树莓派
Laughing
累计撰写
570
篇文章
累计收到
1,424
条评论
首页
栏目
Java
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
广告合作
友链
美女主播
搜索到
8
篇与
的结果
2021-12-18
SpringBoot JPA自动设置创建者、最后修改者
书接上文,SpringBoot JPA自动设置创建时间、修改时间,审计不可能只包含创建时间、最后修改时间,肯定得有人,也就是必须得有创建者、最后修改者。Spring Data Jpa设置创建者、最后修改者也非常简单。实体修改@Data @Entity @Table(name = "Book") @EntityListeners(AuditingEntityListener.class) public class Book { @Id private long id; private String name; private String author; private BigDecimal price; @CreatedDate private Timestamp createdDate; @CreatedBy private String createBy; @LastModifiedDate private Timestamp lastModifiedDate; @LastModifiedBy private String lastModifiedBy; }@CreatedBy注解用于标识创建者。@LastModifiedBy注解用于标识最后修改者。其他注解跟设置创建时间、最后修改时间一致,不再赘述,这里重点说一下,如何获取创建者、最后修改者。设置创建者、最后修改者值在Spring Data Jpa中,可以通过实现AuditorAware接口让程序知道当前审核程序的用户,实现逻辑根据项目实际情况编写。/** * 审计接口,获取当前人员 */ @Configuration public class JpaAuditWare implements AuditorAware<String> { @Override public Optional<String> getCurrentAuditor() { return Optional.of(UUID.randomUUID().toString()); } }验证创建验证 @GetMapping("save") public Book saveBook() { Book book = new Book(); book.setId(1L); book.setName("《山海经》"); book.setAuthor("佚名"); book.setPrice(new BigDecimal("500")); return bookService.saveBook(book); }修改验证然后我们修改一下数据,验证一下最后修改人、最后修改时间[alt type="info"]如果数据未发生改变,那么最后修改者、最后修改时间是不会发生改变的。[/alt]
2021年12月18日
1,713 阅读
0 评论
0 点赞
2021-12-18
SpringBoot JPA自动设置创建时间、修改时间
JPA提供了审计功能,用于设置创建者、创建时间、修改者、修改时间等参数。创建时间、修改时间很好理解,就是当前时间,但是创建者、修改者一般都是通过上下文信息获取的,由于我这边是接口里面使用,未使用创建者、修改者,所以先介绍一下创建时间、修改时间的使用。添加依赖那些巴拉巴拉的就不啰嗦。创建实体@Getter @Setter @ToString @Entity @Table(name = "ARAPDiscountRecord") @EntityListeners(AuditingEntityListener.class) public class ARAPDiscountRecordEntity implements Serializable { @CreatedDate @Column(name = "timestamp_createdon") private Timestamp timestampCreatedon; @LastModifiedDate @Column(name = "timestamp_lastchangedon") private Timestamp timestampLastchangedon; }@CreatedDate注解用于标识创建时间。@LastModifiedDate注解用于标识修改时间。实体类添加@EntityListeners(AuditingEntityListener.class)标识启动审计。启动审计再启用或者配置类上添加@EnableJpaAuditing启动审计。@EnableJpaAuditing @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }这样的话,每次创建数据,系统会自动赋值timestampCreatedon列,修改数据时,系统会自动赋值timestampLastchangedon字段。
2021年12月18日
1,498 阅读
0 评论
0 点赞
2021-07-22
Spring Data Jpa Listener事件的扩展之自定义EntityListener
随着DDD的设计模式逐渐被大家认可和热捧。JPA通过Listener这种机制可以很好地实现事件分离、状体分离。假如,订单的状态变化可能对我们来说比较重要,我们需要定一个类去监听订单状态变更,通知相应的逻辑代码各自去干各自的活。新增一个UserAuditListener类,在相应的操作上添加Callbacks注解@Slf4j public class UserAuditListener { @PostPersist private void postPersist(SysUser sysUser) { recordLog(sysUser, OperateType.CREATE); } @PostRemove private void postRemove(SysUser sysUser) { recordLog(sysUser, OperateType.REMOVE); } @PostUpdate private void postUpdate(SysUser sysUser) { recordLog(sysUser, OperateType.UPDATE); } @PostLoad public void postLoad(SysUser sysUser) { recordLog(sysUser, OperateType.LOAD); } /** * 记录审计日志 * * @param sysUser 用户实体 * @param operateType 操作类型 */ private void recordLog(SysUser sysUser, OperateType operateType) { log.info("{}执行了{}操作", sysUser, operateType.getType()); } } enum OperateType { CREATE("创建"), UPDATE("更新"), REMOVE("删除"), LOAD("查询"); private final String type; OperateType(String type) { this.type = type; } public String getType() { return this.type; } }修改实体,增加@EntityListeners注解@Entity @Table(name = "sys_user") @Data @Slf4j @EntityListeners({UserAuditListener.class}) public class SysUser extends AbstractAuditable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long userId; @JoinColumn(name = "dept_id", referencedColumnName = "dept_id") @ManyToOne(cascade = CascadeType.ALL) private SysDept sysDept; private String userName; private String nickName; private String userType; private String email; @Column(name = "phonenumber") private String phoneNumber; private String sex; private String avatar; @JsonIgnore private String password; @Enumerated(EnumType.STRING) private Status status; private String delFlag; private String loginIp; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp loginDate; private String remark; private Long recycleCompanyId; private Long medicalInstitutionId; private Long ethnicity; @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "sys_user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "role_id")}) private Set<SysRole> sysRoles; }测试这样,我们在增删改查方法调用时,就会执行我们对应的callback注解的方法比如我们插入用户@GetMapping("/save") public Long save(){ SysUser sysUser = new SysUser(); sysUser.setNickName("测试123321"); sysUser.setUserName("测试123321"); sysUser.setSex("0"); sysUserRepository.save(sysUser); return sysUser.getUserId(); }保存后,会自动调用postPersist方法
2021年07月22日
1,300 阅读
0 评论
1 点赞
2021-07-22
Spring Data Jpa扩展之Auditing
Auditing翻译过来是审计和审核。Spring的优秀之处在于帮我们想到了很多我们平时烦琐事情的解决方案,我们在实际的业务系统中,针对一张表的操作大部分是需要记录谁什么时间创建的,谁什么时间修改的,并且能让我们方便地记录操作日志。Spring Data JPA为我们提供了审计功能的架构实现,提供了4个注解专门解决这件事:@CreatedBy:创建人。@CreatedDate:创建时间。@LastModifiedBy:最后修改人。@LastModifiedDate:最后修改时间。增加公共虚拟类一般情况下,创建人、创建时间、最后修改人、最后修改时间四个字段都是统一的。所以,我们可以将其提取到公共的类中,然后所有的实体类继承这个虚拟类。@EntityListeners(AuditingEntityListener.class) @MappedSuperclass public abstract class AbstractAuditable { @CreatedBy private String createBy; @CreatedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp createTime; @LastModifiedBy private String updateBy; @LastModifiedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp updateTime; }[tag type="default"]必须添加@MappedSuperclass注解[/tag]修改实体,继承AbstractAuditable@Entity @Table(name = "sys_user") @Data @Slf4j public class SysUser extends AbstractAuditable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long userId; @JoinColumn(name = "dept_id", referencedColumnName = "dept_id") @ManyToOne(cascade = CascadeType.ALL) private SysDept sysDept; private String userName; private String nickName; private String userType; private String email; @Column(name = "phonenumber") private String phoneNumber; private String sex; private String avatar; @JsonIgnore private String password; @Enumerated(EnumType.STRING) private Status status; private String delFlag; private String loginIp; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp loginDate; private String remark; private Long recycleCompanyId; private Long medicalInstitutionId; private Long ethnicity; @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "sys_user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "role_id")}) private Set<SysRole> sysRoles; }实现AbstractAuditable接口实现AbstractAuditable接口,提供创建者、最后修改者信息,这里我们随便模拟了以下常量。public class MyAuditorAware implements AuditorAware<String> { /** * Returns the current auditor of the application. * * @return the current auditor. */ @Override public Optional<String> getCurrentAuditor() { return Optional.of("测试用户"); } }开启Auditing功能通过@EnableJpaAuditing注解开启JPA的Auditing功能,并且告诉应用AuditorAware的实现类是谁。@SpringBootApplication @EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND) @EnableJpaAuditing public class Example1Application { public static void main(String[] args) { SpringApplication.run(Example1Application.class, args); } @Bean public AuditorAware<String> auditorAware(){ return new MyAuditorAware(); } }测试 @GetMapping("/save") public Long save(){ SysUser sysUser = new SysUser(); sysUser.setNickName("测试123321"); sysUser.setUserName("测试123321"); sysUser.setSex("0"); sysUserRepository.save(sysUser); return sysUser.getUserId(); }
2021年07月22日
1,233 阅读
0 评论
0 点赞
2021-07-22
Spring Data Jpa QueryByExampleExecutor及JpaSpecificationExecutor的用法
QueryByExampleExecutor可以通过实体进行简单的查询。比如我们查询用于昵称是超级开头的用户。@RestController @RequestMapping("/user") public class UserController { @Resource private SysUserRepository sysUserRepository; @GetMapping("/findAll") @Transactional public List<SysUser> findAll() { SysUser sysUser = new SysUser(); sysUser.setNickName("超级"); ExampleMatcher exampleMatcher = ExampleMatcher.matching() .withMatcher("nickName", ExampleMatcher.GenericPropertyMatchers.startsWith()) .withIgnorePaths("focus"); Example<SysUser> sysUserExample = Example.of(sysUser, exampleMatcher); return sysUserRepository.findAll(sysUserExample); } }其实跟MyBatis-Plus类似,功能比较简单,只能拼接and查询,一般使用不是很多。JpaSpecificationExecutor使用Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回一个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来。修改接口public interface SysUserRepository extends JpaRepository<SysUser, Long>, JpaSpecificationExecutor<SysUser> { }测试@RestController @RequestMapping("/user") public class UserController { @Resource private SysUserRepository sysUserRepository; @GetMapping("/findAll") @Transactional public List<SysUser> findAll() { return sysUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> { Predicate p1 = criteriaBuilder.like(root.get("nickName"), "%超级%"); Predicate p2 = criteriaBuilder.equal(root.get("userName"), "admin"); Predicate p3 = criteriaBuilder.equal(root.get("email"),"ry@163.com"); return criteriaBuilder.and(p1, p2); }); } }
2021年07月22日
1,227 阅读
0 评论
0 点赞
2021-07-21
Spring Data Jpa多表关联查询
在权限表中,我们一般会设计用户表、部门表、角色表,一般情况下,一个用户只能属于一个部门,但是一个用户能拥有多个角色,一个角色也可能对应多个部门。Spring Data Jpa中提供了多个注解,用于处理表之间的关联管理。常见注解@OneToOne@OneToOne代表一对一的关联关系,需要配合@JoinColumn一起使用。注意:可以双向关联,也可以只配置一方,需要视实际需求而定。@OneToOne注释五个属性:targetEntity、cascade、fetch、optional和mappedByfetch属性默认值是FetchType.EAGER。optional = true设置属性可以为null;targetEntity属性:Class类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义;cascade属性:CascadeType[]类型。该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。cascade的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表示选择全部四项。@OneToMany、@ManyToOne@OneToMany、@ManyToOne代表一对多和多对一的关系,需要配合@JoinColumn一起使用。比如我们下面例子的用户与部门表,一个用户只属于一个部门,一个部门可以包含多个用户。@ManyToMany@ManyToMany代表多对多的关系。例如我们用于与角色的关联表,一般我们会设计一个用户、角色关联表的对应关系,配合@JoinTable一起使用。示例创建表部门表create table sys_dept ( dept_id bigint auto_increment comment '部门id' primary key, parent_id bigint default 0 null comment '父部门id', ancestors varchar(50) default '' null comment '祖级列表', dept_name varchar(30) default '' null comment '部门名称', order_num int default 0 null comment '显示顺序', leader varchar(20) null comment '负责人', phone varchar(11) null comment '联系电话', email varchar(50) null comment '邮箱', status char default '0' null comment '部门状态(0正常 1停用)', del_flag char default '0' null comment '删除标志(0代表存在 2代表删除)', create_by varchar(64) default '' null comment '创建者', create_time datetime null comment '创建时间', update_by varchar(64) default '' null comment '更新者', update_time datetime null comment '更新时间' ) comment '部门表';用户表create table sys_user ( user_id bigint auto_increment comment '用户ID' primary key, dept_id bigint null comment '部门ID', user_name varchar(30) not null comment '用户账号', nick_name varchar(30) not null comment '用户昵称', user_type varchar(2) default '00' null comment '用户类型(00系统用户)', email varchar(50) default '' null comment '用户邮箱', phonenumber varchar(11) default '' null comment '手机号码', sex char default '0' null comment '用户性别(0男 1女 2未知)', avatar varchar(100) default '' null comment '头像地址', password varchar(100) default '' null comment '密码', status varchar(5) default 'start' null comment '帐号状态(0正常 1停用)', del_flag char default '0' null comment '删除标志(0代表存在 2代表删除)', login_ip varchar(50) default '' null comment '最后登录IP', login_date datetime null comment '最后登录时间', create_by varchar(64) default '' null comment '创建者', create_time datetime null comment '创建时间', update_by varchar(64) default '' null comment '更新者', update_time datetime null comment '更新时间', remark longtext null comment '备注', recycle_company_id bigint null comment '所属回收单位', medical_institution_id bigint null comment '所属医疗机构', ethnicity bigint null comment '民族' ) comment '用户信息表';角色表create table sys_role ( role_id bigint auto_increment comment '角色ID' primary key, role_name varchar(30) not null comment '角色名称', role_key varchar(100) not null comment '角色权限字符串', role_sort int not null comment '显示顺序', data_scope char default '1' null comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', menu_check_strictly tinyint(1) default 1 null comment '菜单树选择项是否关联显示', dept_check_strictly tinyint(1) default 1 null comment '部门树选择项是否关联显示', status char not null comment '角色状态(0正常 1停用)', del_flag char default '0' null comment '删除标志(0代表存在 2代表删除)', create_by varchar(64) default '' null comment '创建者', create_time datetime null comment '创建时间', update_by varchar(64) default '' null comment '更新者', update_time datetime null comment '更新时间', remark varchar(500) null comment '备注' ) comment '角色信息表';用户角色关联表create table sys_user_role ( user_id bigint not null comment '用户ID', role_id bigint not null comment '角色ID', primary key (user_id, role_id) ) comment '用户和角色关联表';创建实体用户实体@Entity @Table(name = "sys_user") @Data @Slf4j public class SysUser { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long userId; @JoinColumn(name = "dept_id", referencedColumnName = "dept_id") @ManyToOne(cascade = CascadeType.ALL) private SysDept sysDept; private String userName; private String nickName; private String userType; private String email; @Column(name = "phonenumber") private String phoneNumber; private String sex; private String avatar; @JsonIgnore private String password; @Enumerated(EnumType.STRING) private Status status; private String delFlag; private String loginIp; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp loginDate; private String createBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp createTime; private String updateBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp updateTime; private String remark; private Long recycleCompanyId; private Long medicalInstitutionId; private Long ethnicity; @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "sys_user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "role_id")}) private Set<SysRole> sysRoles; } 部门实体@Entity @Table(name = "sys_dept") @Getter @Setter @ToString @RequiredArgsConstructor public class SysDept { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "dept_id") private long deptId; private long parentId; private String ancestors; private String deptName; private long orderNum; private String leader; private String phone; private String email; private String status; private String delFlag; private String createBy; private java.sql.Timestamp createTime; private String updateBy; private java.sql.Timestamp updateTime; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; SysDept sysDept = (SysDept) o; return Objects.equals(deptId, sysDept.deptId); } @Override public int hashCode() { return 866095534; } } 角色实体@Entity @Data public class SysRole { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long roleId; private String roleName; private String roleKey; private long roleSort; private String dataScope; private long menuCheckStrictly; private long deptCheckStrictly; private String status; private String delFlag; private String createBy; private java.sql.Timestamp createTime; private String updateBy; private java.sql.Timestamp updateTime; private String remark; } 用户角色关联实体@Entity @IdClass(SysUserRole.class) @Data public class SysUserRole implements Serializable { @Id @Column(name = "user_id") private long userId; @Id @Column(name = "role_id") private long roleId; }Jpa查询接口这个接口不是必须的,可以调用任意的Crud接口。public interface SysUserRepository extends JpaRepository<SysUser, Long> { /** * 根据用户名称查找列表 * * @param userName 用户名称 * @return 列表 */ List<SysUser> findByUserName(String userName); // @Query("select u from SysUser u") Stream<SysUser> readAllBy(); Stream<SysUser> streamAllBy(); @Async Future<List<SysUser>> findAllBy(); @Query("select u from SysUser u where u.userName = :userName and u.email = :email") SysUser findByUserNameAndEmail(@Param("userName") String userName, @Param("email") String email); @Query("select u from SysUser u where u.nickName like %:nickName%") List<SysUser> findAllByNickName(@Param("nickName") String nickName); @Query(value = "select * from sys_user u where email like concat('%',:email,'%')", nativeQuery = true) List<SysUser> findAllByEmailLike(@Param("email") String email); @Query(value = "select u from SysUser u") Page<SysUser> findAllBy(Pageable pageable); SysUser findFirstByUserId(Long userId); @Modifying(clearAutomatically = true) @Query(value = "update SysUser set remark = '234' where userId = :userId") int setRemarkByUserId(@Param("userId") Long userId); }测试@RestController @RequestMapping("/user") public class UserController { @Resource private SysUserRepository sysUserRepository; @GetMapping("/findAll") @Transactional public SysUser findAll() { return sysUserRepository.findFirstByUserId(111L); } }
2021年07月21日
1,331 阅读
0 评论
0 点赞
2021-07-21
Spring Data Jpa使用枚举
有时候在数据库设计的时候,我们可能会使用一些固定的值,比如启用、停用,只有这两个值,我们设计数据库可能设计成stop、start。这个时候,我们在Jpa中设计实体时,一般设置成枚举就更合理了。创建枚举public enum Status { stop("停用"), start("启用"); private String value; Status(String value) { this.value = value; } }实体@Entity @Table(name = "sys_user") @Data @Slf4j public class SysUser { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long userId; private Long deptId; private String userName; private String nickName; private String userType; private String email; @Column(name = "phonenumber") private String phoneNumber; private String sex; private String avatar; @JsonIgnore private String password; @Enumerated(EnumType.STRING) private Status status; private String delFlag; private String loginIp; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp loginDate; private String createBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp createTime; private String updateBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private java.sql.Timestamp updateTime; private String remark; private Long recycleCompanyId; private Long medicalInstitutionId; private Long ethnicity; } 查询我们可以查看一些查询的结果
2021年07月21日
987 阅读
0 评论
0 点赞
2021-07-21
Spring Data Jpa流查询
Spring Data Jpa可以通过使用Java 8 Stream作为返回类型,来逐步处理查询方法的结果,而不是简单的将查询结果包装在Stream数据存储中。接口定义public interface SysUserRepository extends JpaRepository<SysUser, Long> { /** * 根据用户名称查找列表 * * @param userName 用户名称 * @return 列表 */ List<SysUser> findByUserName(String userName); // @Query("select u from SysUser u") Stream<SysUser> readAllBy(); Stream<SysUser> streamAllBy(); }使用@RestController @RequestMapping("/user") public class UserController { @Resource private SysUserRepository sysUserRepository; @GetMapping("/findAll") @Transactional public List<SysUser> findAll() { try (Stream<SysUser> sysUserStream = sysUserRepository.streamAllBy()) { return sysUserStream.collect(Collectors.toList()); } catch (Exception ex) { ex.printStackTrace(); return new ArrayList<>(); } } }注意事项必须通过try catch关闭流方法必须有@Transactional注解
2021年07月21日
1,623 阅读
0 评论
0 点赞