SpringBoot Jpa企业开发示例详细讲解
Buckletime 人气:0JPA 介绍
JPA(Java Persistence API),对象关系映射(ORM)框架规范,是一种Java持久化规范。jpa可以通过实体类生成数据库的表,同时自带很多增删改查方法,大部分sql语句不需要我们自己写,配置完成后直接调用方法即可,很方便。
JPA 简单使用示例
1. pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Data JPA 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- mysql驱动 依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
2. application.properties配置
# 数据库连接配置
spring.datasource.url = jdbc:mysql://localhost:3306/manageserver?serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = 123456
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
# jpa配置
# 自动更新数据库表
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
# 是否在控制台显示Hibernate的sql
spring.jpa.show-sql = false
3. 创建实体类对象,用于映射数据库表
@Table(name="db_dictionary") @Data @Entity public class DbDictionary implements Serializable { @Id @GenericGenerator(name = "faceset_generator", strategy = "uuid") @GeneratedValue(generator = "faceset_generator") @Column private String id; /** * 类型名称 */ @Size(max = 50) @Column @NotNull private String type; /** * 中文 */ @Column @NotNull private String name; /** * 代码 */ @Column @NotNull private String code; /** * 顺序 */ private Integer sort; /** * 描述信息 */ @Column private String remark; private static final long serialVersionUID = 1L; }
4. 创建持久化接口DAO,继承JpaRepository,用于对数据库进行操作
@Repository public interface DictionaryDao extends JpaRepository<DbDictionary, String> { }
5. 至此,JPA基本配置已经完成,这里自带很多内置的增删改查方法,不用我们自己写sql语句,直接调用即可。
JPA 实体类中相关注解说明
@Entity
:表明是一个实体类@Table(name = "dict_info")
:对应的数据表名,与@Entity注解一块使用,但是如果表名和实体类名相同的话,@Table可以省略@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
:自定义hibernate主键生成策略@Id
:表示当前字段为主键@GeneratedValue(generator = "jpa-uuid")
:指定主键生成策略为uuid@Column(name = "DICTNAME")
:当实体类的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明@CreatedDate
:创建时间@LastModifiedDate
:更新时间@Temporal(TemporalType.TIMESTAMP)
:实体类会封装成完整的时间“yyyy-MM-dd hh:MM:ss”的 Date类型@Transient
:表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性
JPA 持久层关键字说明
JPA Data的使用模式已经帮我集成了日常一些关键字用法,通过查询可以直接使用!
关键字 | 方法命名 | sql where字句 |
---|---|---|
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equals | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEquals | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEquals | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,NotNull | findByNameNotNull | where name is not null |
Like | findByNameLike | where name like ? |
NotLike | findByNameNotLike | where name not like ? |
StartingWith | findByNameStartingWith | where name like ‘?%’ |
EndingWith | findByNameEndingWith | where name like ‘%?’ |
Containing | findByNameContaining | where name like ‘%?%’ |
OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
Not | findByNameNot | where name <> ? |
In | findByIdIn(Collection<?> c) | where id in (?) |
NotIn | findByIdNotIn(Collection<?> c) | where id not in (?) |
True | findByAaaTue | where aaa = true |
False | findByAaaFalse | where aaa = false |
IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |
实战-JPA企业开发示例
1. 实体继承基础通用属性
/** * 实体继承映射类基础 ,保存实体的通用属性 */ @Data @Accessors(chain = true) @MappedSuperclass //实体继承映射 public abstract class BaseEntity implements Serializable { /** * 创建者 */ @Basic @Column(length = 50) private String creator; /** * 修改者 */ @Basic @Column(length = 50) private String modifier; /** * 创建时间 */ @Basic @Column(name = "create_time") @CreatedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; /** * 修改时间 */ @Basic @Column(name = "update_time") @LastModifiedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateTime; }
2. 查询
2.1 条件查询
条件查询有两种方式,一是直接使用持久层提供的关键字,二是自己写查询SQL。
// 根据名称和性别查询用户 User findByNameAndSex(String name, String sex);
@Query(nativeQuery = true, value = "select * from user where name = :name and sex = :sex") User findByNameAndSex(@Param("name") String name, @Param("sex") String sex);
2.2 查询排序
List<T> findAll(Sort sort); //按创建时间倒序排列 Sort.by("createTime").descending()
2.3 分页查询
Page<T> findAll(Pageable pageable); /*获取分页参数*/ public PageRequest getPageRequest() { return getPageRequest(Sort.unsorted()); } /*获取分页和排序参数*/ public PageRequest getPageRequest(Sort sort) { ServletRequestAttributes attributes = getServletRequestAttributes(); if (StringUtils.hasText(attributes.getRequest().getParameter("page")) && StringUtils.hasText(attributes.getRequest().getParameter("size"))) { int page = Integer.parseInt(attributes.getRequest().getParameter("page")); int size = Integer.parseInt(attributes.getRequest().getParameter("size")); return PageRequest.of(page, size, sort); } return PageRequest.of(Constants.zero, Constants.ten); }
2.4 动态条件查询
动态条件查询Specification
,DAO需要再继承JpaSpecificationExecuto
r接口
List<T> findAll(@Nullable Specification<T> spec); Specification<ProjectionInfo> spec = (Specification<ProjectionInfo>) (root, query, cb) -> { List<Predicate> predicateList = new ArrayList<>(); // 时间 if (null != startTime && null != endTime) { predicateList.add(cb.between(root.get("createTime"), startTime, endTime)); } // 数字 if (searchDto.getCloud() != null) { predicateList.add(cb.le(root.<Integer>get("cloudPercent"), searchDto.getCloud())); } // 字符串 if (searchDto.getName() != null) { predicateList.add(cb.equal(root.get("name"), searchDto.getName())); } // 列表 if (StrUtil.isNotEmpty(searchDto.getSatellite())) { String[] satellites = searchDto.getSatellite().split(","); Expression<String> exp = root.<String>get("satellite"); predicateList.add(exp.in(Arrays.asList(satellites))); } Predicate[] pre = new Predicate[predicateList.size()]; pre = predicateList.toArray(pre); return query.where(pre).getRestriction(); };
2.5 多表联查
@Query(nativeQuery = true, value = "SELECT satellite, count(id), COALESCE(sum(file_size), 0) FROM t_mas_orbit_info" + " WHERE create_time BETWEEN :startTime AND :endTime " + " GROUP BY satellite") List<Object[]> satelliteDataIncreased(@Param("startTime") Date startTime, @Param("endTime") Date endTime);
2.6 返回自定义Vo
@Query(value = "SELECT new cn.piesat.dispatch.model.vo.FileDataVO(p.id, p.fileName,p.stationCode,p.fileSize, p.fileDate, p.createTime, p.state, p.filePath,p.forwardTime) " + " FROM DbZxjProductInfoDTO p ") List<FileDataVO> getFileList();
3. 修改和删除
进行修改和删除时,需要添加@Modifying
、@Transactional
注解。
@Query(nativeQuery = true, value = "UPDATE db_order_info SET download_count = (SELECT download_count + 1) WHERE id = :orderId ") @Modifying @Transactional int updateDownloadTimes(String orderId);
@Modifying @Transactional void deleteByName(String name);
踩坑
1.删除的方法上一定要加@Transactional和@Modifying注解
2.自定义删除方法的时候如果传的是基本类型或者包装类型一定要用 void deleteByxxx(String s) 而不是 void deleteAllByxxx(String s)。
因为deleteAllByxxx(String s)会被jpa识别为查询语句,只有传入参数是列表时才是用deleteAllByxxx(List<String> s)
推荐使用原生sql,自带的delete或者deleteAll会先进行查询,然后在查询结果上面挨个执行删除,并不是一条sql执行完删除操作,所以还是建议自己写delete
加载全部内容