摘要:關(guān)聯(lián)關(guān)系的關(guān)聯(lián)關(guān)系定義上,感覺并不是很靈活,姿勢也比較難找。如,定義在關(guān)聯(lián)關(guān)系上的參數(shù)可以設(shè)置級聯(lián)的相關(guān)東西。因?yàn)樾蛄谢瘯婕暗綄?shí)體類關(guān)聯(lián)對象的獲取,會觸發(fā)所有的關(guān)聯(lián)關(guān)系。
接(4) - Database 系列.
Java Persistence API,可以理解就是 Java 一個(gè)持久化標(biāo)準(zhǔn)或規(guī)范,Spring Data JPA 是對它的實(shí)現(xiàn)。并且提供多個(gè) JPA 廠商適配,如 Hibernate、Apache 的 OpenJpa、Eclipse的EclipseLink等。
spring-boot-starter-data-jpa 默認(rèn)使用的是 Hibernate 實(shí)現(xiàn)。
直接引入依賴:
org.springframework.boot spring-boot-starter-data-jpa
開啟 SQL 調(diào)試:
spring.jpa.database=mysql spring.jpa.show-sql=true
在 SpringBoot + Spring Data Jpa 中,不需要額外的配置什么,只需要編寫實(shí)體類(Entity)與數(shù)據(jù)訪問接口(Repository)就能開箱即用,Spring Data JPA 能基于接口中的方法規(guī)范命名自動的幫你生成實(shí)現(xiàn)(根據(jù)方法命名生成實(shí)現(xiàn),是不是很牛逼?)
Spring Data JPA 還默認(rèn)提供了幾個(gè)常用的Repository接口:
Repository: 僅僅是一個(gè)標(biāo)識,沒有任何方法,方便 Spring 自動掃描識別
CrudRepository: 繼承 Repository,實(shí)現(xiàn)了一組 CRUD 相關(guān)的方法
PagingAndSortingRepository: 繼承 CrudRepository,實(shí)現(xiàn)了一組分頁排序相關(guān)的方法
JpaRepository: 繼承 PagingAndSortingRepository,實(shí)現(xiàn)一組JPA規(guī)范相關(guān)的方法
推薦教程:Spring Data JPA實(shí)戰(zhàn)入門訓(xùn)練 https://course.tianmaying.com...
Entity 實(shí)體和 Respository 接口根據(jù) user 表結(jié)構(gòu),我們定義好 User 實(shí)體類與 UserRespository 接口類。
這里,還自定義了一個(gè) @Query 接口,為了體驗(yàn)下自定義查詢。因?yàn)槭褂昧?lombok,所以實(shí)體類看起來很干凈。
User.java
@Data @Entity public class User { @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column(nullable = false, unique = true, updatable = false) @JsonProperty(value = "email") private String username; @Column(nullable = false) @JsonIgnore private String password; @Column(nullable = false) @JsonIgnore private String salt; @Column(nullable = true) private Date birthday; @Column(nullable = false) private String sex; @Column(nullable = true) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp access; @Column(nullable = true) @JsonFormat(pattern="HH:mm:ss") private Time accessTime; @Column(nullable = false) private Integer state; @Column(nullable = false, insertable = false, updatable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp created; @Column(nullable = false, insertable = false, updatable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp updated; }
@Data 是 lombok 的注解,自動生成Getter,Setter,toString,構(gòu)造函數(shù)等
@Entity 注解這是個(gè)實(shí)體類
@Table 注解表相關(guān),如別名等
@Id 注解主鍵,@GeneratedValue 表示自動生成
@DynamicUpdate,@DynamicInsert 注解可以動態(tài)的生成insert、update 語句,默認(rèn)會生成全部的update
@Column 標(biāo)識一些字段特性,字段別名,是否允許為空,是否唯一,是否進(jìn)行插入和更新(比如由MySQL自動維護(hù))
@Transient 標(biāo)識該字段并非數(shù)據(jù)庫字段映射
@JsonProperty 定義 Spring JSON 別名,@JsonIgnore 定義 JSON 時(shí)忽略該字段,@JsonFormat 定義 JSON 時(shí)進(jìn)行格式化操作
UserRepository.java
public interface UserRepository extends JpaRepository, UserCustomRepository { User findByUsername(String username); @Transactional @Modifying @Query("UPDATE User SET state = ?2 WHERE id = ?1 ") Integer saveState(Long id, Integer state); }
@Transactional 用來標(biāo)識事務(wù),一般修改、刪除會用到, @Modifying 標(biāo)識這是個(gè)修改、刪除的Query
@Param 標(biāo)注在參數(shù)上,可用于標(biāo)識參數(shù)式綁定(不使用 ?1 而使用 :param)
好了,接下來我們就可以進(jìn)行單表的增、刪、改、查分頁排序操作了:
@Autowired private UserRepository userRepository; User user = new User(); userRepository.save(user); // 插入或保存 userRepository.saveFlush(user); // 保存并刷新 userRepository.exists(1) // 主鍵查詢是否存在 userRepository.findOne(1); // 主鍵查詢單條 userRepository.delete(1); // 主鍵刪除 userRepository.findByUsername("[email protected]"); // 查詢單條 userRepository.findAll(pageable); // 帶排序和分頁的查詢列表 userRepository.saveState(1, 0); // 更新單個(gè)字段
通常,exist(),delete()之類的方法,我們可能直接會操作 UserRepository,但是一般情況下,在 UserRepository 上面還會提供一個(gè) UserService 來進(jìn)行一系列的操作(比如數(shù)據(jù)校驗(yàn),邏輯判斷之類)
分頁和排序PagingAndSortingRepository 和 JpaRepository 接口都具有分頁和排序的功能。因?yàn)楹笳呃^承自前者。比如下面這個(gè)方法:
PagefindAll(Pageable var1);
Pageable 是Spring Data庫中定義的一個(gè)接口,該接口是所有分頁相關(guān)信息的一個(gè)抽象,通過該接口,我們可以得到和分頁相關(guān)所有信息(例如pageNumber、pageSize等),這樣,Jpa就能夠通過pageable參數(shù)來組裝一個(gè)帶分頁信息的SQL語句。
Page 類也是Spring Data提供的一個(gè)接口,該接口表示一部分?jǐn)?shù)據(jù)的集合以及其相關(guān)的下一部分?jǐn)?shù)據(jù)、數(shù)據(jù)總數(shù)等相關(guān)信息,通過該接口,我們可以得到數(shù)據(jù)的總體信息(數(shù)據(jù)總數(shù)、總頁數(shù)...)以及當(dāng)前數(shù)據(jù)的信息(當(dāng)前數(shù)據(jù)的集合、當(dāng)前頁數(shù)等)
Pageable只是一個(gè)抽象的接口??梢酝ㄟ^兩種途徑生成 Pageable 對象:
通過參數(shù),自己接收參數(shù),自己構(gòu)造生成 Pageable 對象
@RequestMapping(value = "", method = RequestMethod.GET) public Object page(@RequestParam(name = "page", required = false) Integer page, @RequestParam(name="size", required = false) Integer size) { Sort sort = new Sort(Sort.Direction.DESC, "id"); Pageable pageable = new PageRequest(page, size, sort); Pageusers = userRepository.findAll(pageable); return this.responseData(users); }
這種方式你可以靈活的定義傳參。
通過 @PageableDefault 注解,會把參數(shù)自動注入成 Pageable 對象,默認(rèn)是三個(gè)參數(shù)值:
page=,第幾頁,從0開始,默認(rèn)為第0頁
size=,每一頁的大小
sort=,排序相關(guān)的信息,例如sort=firstname&sort=lastname,desc
@RequestMapping(value = "/search", method = RequestMethod.GET) public Object search(@PageableDefault(size = 3, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) { Pageusers = userRepository.findAll(pageable); return this.responseData(users); }
看起來,這種方式更優(yōu)雅一些。
關(guān)聯(lián)關(guān)系Spring Data JPA 的關(guān)聯(lián)關(guān)系定義上,感覺并不是很靈活,姿勢也比較難找。
視頻教程:http://www.jikexueyuan.com/co...
OneToOne 一對一一對一的關(guān)系,拿 user,user_detail 來說,一般應(yīng)用起來,有以下幾種情況:
主鍵直接關(guān)聯(lián):user(id, xx);user_detail(id, xx) 或 user(id, xx),user_detail(user_id, xx) 其中 id, userid 為主鍵
主表含外鍵的關(guān)聯(lián):user(id, role_id, xx);role(id, xx) 。 其中 id 為自增主鍵
附表含外鍵的關(guān)聯(lián):user(id, xx);user_detail(id, user_id, xx) 。其中 id 為自增主鍵
主表含外鍵的關(guān)聯(lián):用戶->角色是一對一,而角色->用戶是多對一,而大部分情況,我們是通過 user 表來查詢某個(gè)角色的列表,而通過 role 來查詢某個(gè)角色的列表可能性很小。
附表表含外鍵的關(guān)聯(lián):其實(shí)和主表含外鍵的關(guān)聯(lián)完全相反,關(guān)聯(lián)的定義也是相反的。
主鍵ID關(guān)聯(lián)單向關(guān)聯(lián),直接在 User 上定義 @OneToOne 與 @PrimaryKeyJoinColumn 即可完成
@Entity @Data public class User { ... @OneToOne @PrimaryKeyJoinColumn private UserDetail detail; ... } // 獲取的user,會包含detail屬性 User user = userRepository.findOne(userId);
雙向關(guān)聯(lián),除了要定義 User 的 @OneToOne,還需要定義 UserDetail 的 @OneToOne,用 mappedBy 指示 User 表的屬性名。
@Entity @Data public class UserDetail { ... @OneToOne(mappedBy = "detail") private User user; ... }
出問題了,雙向關(guān)聯(lián),涉及到一個(gè)循環(huán)引用無限遞歸的問題,這個(gè)問題會發(fā)生在 toString、 JSON 轉(zhuǎn)換上??赡苓@只是個(gè)基礎(chǔ)問題,但對于我這個(gè)入門漢,抓瞎了好長時(shí)間。
解決辦法:
分別給User、UserDetail的關(guān)聯(lián)屬性加上:@JsonManagedReference、@JsonBackReference注解,解決 JSON 問題
給 UserDetail 實(shí)體類加上 @ToString(exclude = "user") 注解,解決 toString 的問題。
所以 UserDetail 最終造型應(yīng)該是這樣的:
@Entity @Data @ToString(exclude = "user") public class UserDetail { ... @OneToOne(mappedBy = "detail") @JsonBackReference private User user; } // 現(xiàn)在可以進(jìn)行雙向查詢了 User user1 = userRepository.findOne(userId); userDetail userdetail = userDetailRepository.findOne(userId); User user2 = userdetail.getUser();
@PrimaryKeyJoinColumn 注解主要用于主鍵關(guān)聯(lián),注意實(shí)體屬性需要使用 @Id 的為主鍵,假如現(xiàn)在是:user(id, xx),user_detail(user_id, xx) 這種情況。則需要在 User 類上自定義它的屬性:
// User @OneToOne @PrimaryKeyJoinColumn(referencedColumnName = "user_id") @JsonManagedReference private UserDetail detail;主表含外鍵
使用 @JoinColumn 注解即可完成,默認(rèn)使用的外鍵是(屬性名+下劃線+id)。關(guān)聯(lián)附表的主鍵 id。
可以通過 name=,referencedColumnName= 屬性重新自定義。
@Entity @Data public class User { ... // 屬性名為role,所以 @JoinColumn 會默認(rèn)外鍵是 role_id @OneToOne @JoinColumn @JsonManagedReference private Role role; ... }
對于 user->role 的表關(guān)聯(lián)需求,我們不需要定義 OneToOne 反向關(guān)系,并且 role->user 本來是個(gè)一對多關(guān)系。
附表含外鍵這種情況一般也會經(jīng)常出現(xiàn),它可以保證每個(gè)表都有一個(gè)自增主鍵的id
因?yàn)橥怄I在附表上,所以需要反過來,在 User 上定義 mapped。
如果是雙向關(guān)聯(lián),同樣需要加上忽略 toString(),JSON 的注解
@Entity @Data public class User { ... @OneToOne(mappedBy = "user") @JsonManagedReference private UserDetail detail; ... } @Entity @Data @ToString(exclude = "user") public class UserDetail { ... @OneToOne @JoinColumn @JsonBackReference private User user; ... } User user1 = userRepository.findOne(userId); // 給 UserDetail 定義一個(gè)獨(dú)立的 findByUserId 接口,這樣可以通過操作 UserDetail 反向獲取到 user 的數(shù)據(jù) userDetail userdetail = userDetailRepository.findByUserId(userId); User user2 = userdetail.getUser();
實(shí)際上,在上面的例子里面,考慮實(shí)際的場景,幾乎不需要定義 OneToOne 的反向關(guān)聯(lián)(偽需求),這樣就不用解決循環(huán)引用的問題了。這里只是意淫,不是嗎?
現(xiàn)在有個(gè)問題出現(xiàn)了,這種情況下(附表含外鍵),我如何定義 User->UserDetail 的單向關(guān)系呢?
關(guān)聯(lián)關(guān)系:一對多接著上面的例子,Role -> User 實(shí)際上是個(gè)一對多的關(guān)系。但我們一般不會這么做。直接通過 User 就可以查詢嘛。所以這里演示另一個(gè)例子。
User->Order 是一對多,Order->User 是多對一,定義 Order 實(shí)體,注意@Table 注解,因?yàn)?order 是 MySQL 關(guān)鍵詞(此處中槍)
@Entity @Data @Table(name = "`order`") public class Order { @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; }
然后在 User 中定義 @OneToMany,因?yàn)槭且粚Χ?,所以返回的是List
@OneToMany(fetch = FetchType.LAZY) @JoinColumn(name="user_id") private Listorders;
測試一下:
User user = userService.findOne(userId); if (user != null) { // LAZY 的緣故,在 getOrders 才會觸發(fā)獲取操作 Listorders = user.getOrders(); return this.responseData(orders); }
再看看反向關(guān)聯(lián),也就是 @ManyToOne,稍作調(diào)整
User 實(shí)體類 @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") private Listorders; Order 實(shí)體類 @ManyToOne private User user;
再測試一下:
Order order = orderRepository.findOne(orderId); if (order != null) { User user = order.getUser(); return this.responseData(user); }總結(jié)
想想實(shí)際場景,我們不太需要定義 User->Order 這種關(guān)聯(lián),因?yàn)橛脩艨赡苡泻芏嘤唵?,這個(gè)量是無可預(yù)測的。這時(shí)候這種關(guān)聯(lián)查詢,不能分頁,沒有意義(也可能是我姿勢不對)。
如果是有限的 XToMany 關(guān)聯(lián),是有意義的。比如配置管理。一個(gè)應(yīng)用擁有有限的多項(xiàng)配置?
Order->User 這種關(guān)聯(lián)是有意義的。拿到一個(gè) order_id 去反查用戶信息。
關(guān)聯(lián)關(guān)系:多對多Order <-> Product 是多對多的關(guān)系,關(guān)聯(lián)表是 order_product,
Order 實(shí)體配置 @ManyToMany 屬性,不需要定義 OrderProduct 實(shí)體類,
// @JoinTable 實(shí)際可以省略,因?yàn)槭褂玫氖悄J(rèn)配置 @ManyToMany(fetch = FetchType.LAZY) @JoinTable( name = "order_product", joinColumns = @JoinColumn(name = "order_id"), inverseJoinColumns = @JoinColumn(name = "product_id")) @JsonManagedReference private Listproducts;
這樣就定義了單向關(guān)聯(lián),雙向關(guān)聯(lián)類似在 Product 實(shí)體配置:
@ManyToMany(mappedBy = "products", fetch = FetchType.LAZY) @JsonIgnore private Listorders;
好了,這樣就OK了,實(shí)際按照上面的解釋,Product -> Order 是不太有意義的。
屬性參數(shù)@OneToOne的屬性:
cascade 屬性表示級聯(lián)操作策略,有 CascadeType.ALL 等值。
fetch 屬性表示實(shí)體的加載方式,有 FetchType.LAZY 和 FetchType.EAGER 兩種取值,默認(rèn)值為 EAGER
拿OneToOne來說,如果是 EAGER 方式,那么會產(chǎn)生一個(gè)連接查詢,如果是 LAZY 方式,則是兩個(gè)查詢。并且第二個(gè)查詢會在用的時(shí)候才會觸發(fā)(僅僅.getXXX是不夠的)。
級聯(lián)在未定義級聯(lián)的情況下,我們通常需要手動插入。
如 user(id, xx),user_detail(id, user_id, xx)
User user = new User(); userRepository.save(user); UserDetail userDetail = new UserDetail(); userDetail.setUserId(user.getId()); userDetailRepository.save(userDetail);
定義在關(guān)聯(lián)關(guān)系上的 cascade 參數(shù)可以設(shè)置級聯(lián)的相關(guān)東西。
經(jīng)過一番研究,這部分暫時(shí)我還沒搞明白正確姿勢,玩不轉(zhuǎn)。
復(fù)雜的查詢 問題總結(jié) 數(shù)據(jù)庫默認(rèn)值字段,插入后不會自動返回默認(rèn)值。Entity not return default value after insert一般關(guān)鍵表會記錄創(chuàng)建、更新時(shí)間,滿足基本審計(jì)需求,以前我喜歡使用 MySQL 默認(rèn)值特性,這樣應(yīng)用層就可以不用管他們了,如:
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
在實(shí)體中,我們要忽略插入和更新對他們的操作。
@Column(nullable = false, insertable = false, updatable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp created; @Column(nullable = false, insertable = false, updatable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp updated;
看起來不錯(cuò)哦,工作正常,但是:
Spring Data Jpa 在 save() 完成以后,對于這種數(shù)據(jù)庫默認(rèn)插入的值,拿不到回寫的數(shù)據(jù)啊,無論我嘗試網(wǎng)上的方法使用 saveAndFlush() 還是手動 flush() 都是扯淡。
這個(gè)坑,我踩了好久,到現(xiàn)在,依然不知道這種情況怎么解決。
臨時(shí)解決方案:
拋棄數(shù)據(jù)庫默認(rèn)值特性,在實(shí)體類借助 @PrePersist、@PreUpdate 手動實(shí)現(xiàn),如果有多個(gè)表,遵循同一規(guī)范,可以搞個(gè)基類,雖然不太爽,但是能正常工作。
@MappedSuperclass @Getter @Setter public class BaseEntity { @Column(nullable = false, updatable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp created; @Column(nullable = false) @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Timestamp updated; @PrePersist public void basePrePersist() { long timestamp = new java.util.Date().getTime(); created = new Timestamp(timestamp); updated = new Timestamp(timestamp); } @PreUpdate public void basePreUpdate() { updated = new Timestamp(new java.util.Date().getTime()); } }OneToOne 關(guān)聯(lián)關(guān)系,指定 FetchType.LAZY,JSON 時(shí)會出錯(cuò),得不到數(shù)據(jù)
原因大概是,JSON序列化的時(shí)候,數(shù)據(jù)還沒有fetch到,出錯(cuò)信息如下:
Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer
解決方法:
application.properties 增加配置項(xiàng):
spring.jackson.serialization.fail-on-empty-beans=false
然而你會發(fā)現(xiàn)最終的 JSON 多出來兩個(gè)key,分別是handler、hibernateLazyInitializer
所以還需要在實(shí)體類上增加注解:
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
搞定!
關(guān)于循環(huán)引用和 Lazy Fetch接上個(gè)問題,這里要思考一個(gè)問題場景:
Lazy Fetch 在 JSON 序列化實(shí)體類時(shí)失效
我們定義了一個(gè) User 實(shí)體類,這個(gè)實(shí)體類有幾個(gè)關(guān)聯(lián),比如 OneToOne和 OneToMany,并且設(shè)置了Lazy,我們執(zhí)行了 findOne 查詢并返回結(jié)果,在 RestController 的時(shí)候,會默認(rèn)執(zhí)行 Jackson 的序列化JSON 操作。
因?yàn)樾蛄谢瘯婕暗綄?shí)體類關(guān)聯(lián)對象的獲取,會觸發(fā)所有的關(guān)聯(lián)關(guān)系。生成一大堆的查詢 SQL, 這樣 LAZY 就失去意義了啊,比如我只想要 User 單表的基本信息怎么辦?
stackoverflow 可以搜到了好多類似問題,我目前還沒找到正確的姿勢。
可以想象的是,不應(yīng)當(dāng)將實(shí)體類直接返回給客戶端,應(yīng)該再定義一個(gè)返回?cái)?shù)據(jù)的DTO,將實(shí)體類的數(shù)據(jù)復(fù)制到DTO,然后返回并JSON。然而這樣好蛋疼,隨便一個(gè)項(xiàng)目你至少需要定義實(shí)體類,輸入?yún)?shù)的DTO,輸出參數(shù)的DTO。
問題暫放這里。
循環(huán)引用
我們雖然通過 @JsonBackReference 和 JsonManagedReference 來解決。但是有時(shí)候,對于兩個(gè) OneToOne 實(shí)體,我們都需要 JSON 序列化怎么辦?如 User 與 UserDetail
另一個(gè)辦法,給實(shí)體類加上 @JsonIdentityInfo:
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
這樣好處是顯而易見的,只需要在實(shí)體類上注解一下即可。
猜測原理是引入了id,檢測了主鍵是否一致,決定是否引用下去。如 User->UserDetail->User。
所以他還會多一次查詢,并且關(guān)聯(lián)數(shù)據(jù)上會多一個(gè)關(guān)聯(lián)關(guān)系的 id 的字段。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67271.html
摘要:開始介紹簡化了基于的應(yīng)用開發(fā),你只需要就能創(chuàng)建一個(gè)獨(dú)立的,產(chǎn)品級別的應(yīng)用。該包含很多搭建,快速運(yùn)行項(xiàng)目所需的依賴,并提供一致的,可管理傳遞性的依賴集。日志級別通過標(biāo)識開啟控制臺級別日志記錄,也可以在中指定日志級別配置示例 開始 介紹 Spring Boot 簡化了基于 Spring 的應(yīng)用開發(fā),你只需要 run 就能創(chuàng)建一個(gè)獨(dú)立的,產(chǎn)品級別的 Spring 應(yīng)用。 Spring 平臺...
摘要:本文只是引子,后續(xù)更新到獨(dú)立章節(jié)。尤其是,這也是現(xiàn)在號稱流行的組合。幸虧現(xiàn)在看起來不主流了。增刪改查多條件組合查詢分頁,排序等多表關(guān)聯(lián)。而每個(gè)類寫上構(gòu)造函數(shù),,實(shí)在是蛋疼。 本文只是引子,后續(xù)更新到獨(dú)立章節(jié)。 環(huán)境:Spring Boot 1.5.4 到了操作數(shù)據(jù)庫的環(huán)節(jié),以 MySQL 為基準(zhǔn),體驗(yàn)一下數(shù)據(jù)庫的相關(guān)操作,先讓我糾結(jié)一下,至少有以下四種姿勢。 JDBC。原生的 JD...
摘要:與的關(guān)系是什么是官方提出的持久化規(guī)范。它為開發(fā)人員提供了一種對象關(guān)聯(lián)映射工具來管理應(yīng)用中的關(guān)系數(shù)據(jù)。他的出現(xiàn)主要是為了簡化現(xiàn)有的持久化開發(fā)工作和整合技術(shù),結(jié)束現(xiàn)在,,等框架各自為營的局面。定義了在對數(shù)據(jù)庫中的對象處理查詢和事務(wù)運(yùn)行時(shí)的的。 導(dǎo)讀: 在上篇文章中對Spring MVC常用的一些注解做了簡要的說明,在這篇文章中主要對Spring Data JPA 做一個(gè)簡要的說明,并附有一...
摘要:初次使用的人往往會困惑,不知道該使用哪種方法。目前來說,團(tuán)隊(duì)推薦使用基于的方法來提供更高的靈活性。配置,從而在應(yīng)用啟動時(shí)執(zhí)行腳本來初始化數(shù)據(jù)庫。目前為止我們沒有任何消息需要配置,所以只在文件夾中創(chuàng)建一個(gè)空的文件。將配置為,它包含的上下文。 前言 spring是一個(gè)用于創(chuàng)建web和企業(yè)應(yīng)用的一個(gè)很流行的框架。和別的只關(guān)注于一點(diǎn)的框架不同,Spring框架通過投資并組合項(xiàng)目提供了大量的功能...
摘要:下一代服務(wù)端開發(fā)下一代服務(wù)端開發(fā)第部門快速開始第章快速開始環(huán)境準(zhǔn)備,,快速上手實(shí)現(xiàn)一個(gè)第章企業(yè)級服務(wù)開發(fā)從到語言的缺點(diǎn)發(fā)展歷程的缺點(diǎn)為什么是產(chǎn)生的背景解決了哪些問題為什么是的發(fā)展歷程容器的配置地獄是什么從到下一代企業(yè)級服務(wù)開發(fā)在移動開發(fā)領(lǐng)域 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》 Kotlin + Spring Boot : 下一代 Java...
閱讀 3529·2021-11-17 17:01
閱讀 3936·2021-11-08 13:12
閱讀 2491·2021-10-08 10:04
閱讀 711·2021-09-29 09:35
閱讀 1431·2021-09-26 10:12
閱讀 2068·2021-09-07 09:58
閱讀 1967·2019-08-30 15:55
閱讀 2146·2019-08-30 13:14