SpringBoot Jpa企業(yè)開(kāi)發(fā)示例詳細(xì)講解
JPA 介紹
JPA(Java Persistence API),對(duì)象關(guān)系映射(ORM)框架規(guī)范,是一種Java持久化規(guī)范。jpa可以通過(guò)實(shí)體類生成數(shù)據(jù)庫(kù)的表,同時(shí)自帶很多增刪改查方法,大部分sql語(yǔ)句不需要我們自己寫,配置完成后直接調(diào)用方法即可,很方便。
JPA 簡(jiǎn)單使用示例
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驅(qū)動(dòng) 依賴 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
2. application.properties配置
# 數(shù)據(jù)庫(kù)連接配置
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配置
# 自動(dòng)更新數(shù)據(jù)庫(kù)表
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
# 是否在控制臺(tái)顯示Hibernate的sql
spring.jpa.show-sql = false
3. 創(chuàng)建實(shí)體類對(duì)象,用于映射數(shù)據(jù)庫(kù)表
@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. 創(chuàng)建持久化接口DAO,繼承JpaRepository,用于對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
@Repository public interface DictionaryDao extends JpaRepository<DbDictionary, String> { }
5. 至此,JPA基本配置已經(jīng)完成,這里自帶很多內(nèi)置的增刪改查方法,不用我們自己寫sql語(yǔ)句,直接調(diào)用即可。
JPA 實(shí)體類中相關(guān)注解說(shuō)明
@Entity
:表明是一個(gè)實(shí)體類@Table(name = "dict_info")
:對(duì)應(yīng)的數(shù)據(jù)表名,與@Entity注解一塊使用,但是如果表名和實(shí)體類名相同的話,@Table可以省略@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
:自定義hibernate主鍵生成策略@Id
:表示當(dāng)前字段為主鍵@GeneratedValue(generator = "jpa-uuid")
:指定主鍵生成策略為uuid@Column(name = "DICTNAME")
:當(dāng)實(shí)體類的屬性與其映射的數(shù)據(jù)庫(kù)表的列不同名時(shí)需要使用@Column 標(biāo)注說(shuō)明@CreatedDate
:創(chuàng)建時(shí)間@LastModifiedDate
:更新時(shí)間@Temporal(TemporalType.TIMESTAMP)
:實(shí)體類會(huì)封裝成完整的時(shí)間“yyyy-MM-dd hh:MM:ss”的 Date類型@Transient
:表示該屬性并非一個(gè)到數(shù)據(jù)庫(kù)表的字段的映射,ORM框架將忽略該屬性
JPA 持久層關(guān)鍵字說(shuō)明
JPA Data的使用模式已經(jīng)幫我集成了日常一些關(guān)鍵字用法,通過(guò)查詢可以直接使用!
關(guān)鍵字 | 方法命名 | 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(?) |
實(shí)戰(zhàn)-JPA企業(yè)開(kāi)發(fā)示例
1. 實(shí)體繼承基礎(chǔ)通用屬性
/** * 實(shí)體繼承映射類基礎(chǔ) ,保存實(shí)體的通用屬性 */ @Data @Accessors(chain = true) @MappedSuperclass //實(shí)體繼承映射 public abstract class BaseEntity implements Serializable { /** * 創(chuàng)建者 */ @Basic @Column(length = 50) private String creator; /** * 修改者 */ @Basic @Column(length = 50) private String modifier; /** * 創(chuàng)建時(shí)間 */ @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; /** * 修改時(shí)間 */ @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 條件查詢
條件查詢有兩種方式,一是直接使用持久層提供的關(guān)鍵字,二是自己寫查詢SQL。
// 根據(jù)名稱和性別查詢用戶 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); //按創(chuàng)建時(shí)間倒序排列 Sort.by("createTime").descending()
2.3 分頁(yè)查詢
Page<T> findAll(Pageable pageable); /*獲取分頁(yè)參數(shù)*/ public PageRequest getPageRequest() { return getPageRequest(Sort.unsorted()); } /*獲取分頁(yè)和排序參數(shù)*/ 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 動(dòng)態(tài)條件查詢
動(dòng)態(tài)條件查詢Specification
,DAO需要再繼承JpaSpecificationExecuto
r接口
List<T> findAll(@Nullable Specification<T> spec); Specification<ProjectionInfo> spec = (Specification<ProjectionInfo>) (root, query, cb) -> { List<Predicate> predicateList = new ArrayList<>(); // 時(shí)間 if (null != startTime && null != endTime) { predicateList.add(cb.between(root.get("createTime"), startTime, endTime)); } // 數(shù)字 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 多表聯(lián)查
@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. 修改和刪除
進(jìn)行修改和刪除時(shí),需要添加@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.自定義刪除方法的時(shí)候如果傳的是基本類型或者包裝類型一定要用 void deleteByxxx(String s) 而不是 void deleteAllByxxx(String s)。
因?yàn)閐eleteAllByxxx(String s)會(huì)被jpa識(shí)別為查詢語(yǔ)句,只有傳入?yún)?shù)是列表時(shí)才是用deleteAllByxxx(List<String> s)
推薦使用原生sql,自帶的delete或者deleteAll會(huì)先進(jìn)行查詢,然后在查詢結(jié)果上面挨個(gè)執(zhí)行刪除,并不是一條sql執(zhí)行完刪除操作,所以還是建議自己寫delete
到此這篇關(guān)于SpringBoot Jpa企業(yè)開(kāi)發(fā)示例詳細(xì)講解的文章就介紹到這了,更多相關(guān)SpringBoot Jpa內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot實(shí)現(xiàn)單文件和多文件上傳
這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)單文件和多文件上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11Java之System.getProperty()的作用及使用說(shuō)明
這篇文章主要介紹了Java之System.getProperty()的作用及使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Json轉(zhuǎn)list二層解析轉(zhuǎn)換代碼實(shí)例
這篇文章主要介紹了Json轉(zhuǎn)list二層解析轉(zhuǎn)換代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12JAVA中使用雙括號(hào)來(lái)初始化靜態(tài)常量的小技巧
這篇文章主要介紹了JAVA中使用雙括號(hào)來(lái)初始化靜態(tài)常量的小技巧,需要的朋友可以參考下2014-06-06在springboot中實(shí)現(xiàn)個(gè)別bean懶加載的操作
這篇文章主要介紹了在springboot中實(shí)現(xiàn)個(gè)別bean懶加載的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10spring-data-redis連接操作redis的實(shí)現(xiàn)
spring-data-redis則是對(duì)Jedis進(jìn)行了高度封裝,使用起來(lái)非常方便。本文主要介紹了spring-data-redis連接操作redis的實(shí)現(xiàn),感興趣的可以了解一下2021-07-07spring boot入門開(kāi)始你的第一個(gè)應(yīng)用
這篇文章主要介紹了spring boot入門開(kāi)始你的第一個(gè)應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06