本片文章我們主要介紹spring-boot如何進行JPA的配置以及如何進行實體間的一對多配置。
依賴準備
要在spring-boot使用jpa需要在專案中有進入相關的依賴,pom檔案里加入下面內容
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
專案的配置檔案中需要對資料庫連結以及jpa進行配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/missyou?characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 12345678
jpa:
hibernate:
ddl-auto: update # 只針對新增的entity建立表
properties:
hibernate:
show_sql: true # 在對資料庫進行操作的時候列印出sql,方便在生產環境排查問題
format_sql: true # 列印sql的時候進行格式化,看起來方便
jpa實戰
- 一對多關係
先定義兩個實體類Banner和BannerItem,一個Banner可以對應多個BannerItem,屬於典型的一對多的關係
@Entity
public class Banner {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(length = 16)
private String name;
@Transient // 表明這個欄位不會對映到表中的欄位
private String description;
private String img;
private String title;
@OneToMany
private List<BannerItem> items; // 關聯屬性,導航屬性
}
@Entity
public class BannerItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String img;
private String keyword;
private Short type;
private String name;
}
先對上面程式碼中的一些註解進行說明:
@Entity標記當前類為一個實體,對應資料庫中的一張表,用來表示這張表資訊,類名預設就是表名,jpa會根據命名規則自動小寫並加下劃線,比如BannerItem實體,生成的表名就是banner_item
@Id表名標記的欄位將作為主鍵
@GeneratedValue(strategy = GenerationType.IDENTITY) 設定id為自增長
@Column(length = 16) 設定欄位的屬性,比如長度、是否為空、是否唯一等
@OneToMany可以使用兩個實體建立一對多的關係,也就是一個Banner可以包含多個BannerItem
@Transient註解表示被標記的當前欄位不會對映到資料庫表的欄位,也就是說生成的表中不會包含這個欄位
此時執行程式,就會在資料庫中建立對應的表:
這裡生成了三張表,banner表和banner_item表我們知道是對應的Banner實體和BannerItem實體,那banner_items這張表是怎麼回事呢?
在解釋這張表之前,我們先來看一下這個表的結構:
表裡只有兩個欄位,banner_id和items_id,分別是banner的id和banner_item的id,這就是說這張表相當於一張關係表,在多對多的時候我們才需要一張關係表,而現在只是一對多,為什麼會產生這張表呢?
這是因為在上面的實體定義的時候,我們只是給這兩個實體建立了關係,並沒有任何一個欄位來表明哪一個BannerItem屬於哪一個Banner,那JPA看到你沒有做,那就我來做,他會自動幫你建立這樣一張關係表來維護這種歸屬關係。那有沒有辦法去掉這張表呢,當然有。
這個時候就需要新增一個外來鍵欄位了,來表明一個banner_item到底是歸屬於哪一個banner,我們來修改一下上面的實體定義:
Banner實體裡做如下修改:
@OneToMany
@JoinColumn(name = "bannerId")
private List<BannerItem> items;
@JoinColumn註解指定外來鍵
BannerItem實體增加一個欄位:bannerId
private Long bannerId;
刪除之前的表,重新執行程式
這個時候生成的表就只有兩個了,在banner_item表裡會新增一個外來鍵欄位。
下面我們通過一個程式例項來驗證上面的內容:
1、構造資料
表結構已經構造好了,現在我們填充一些資料,來使用JPA進行資料查詢
INSERT INTO missyou.banner (id, img, name, title) VALUES (1, 'http://sss.jpg', '頂部banner', '頂部banner');
INSERT INTO missyou.banner (id, img, name, title) VALUES (2, 'http://aaa.jpg', '頂部banner2', '頂部banner2');
INSERT INTO missyou.banner_item (id, banner_id, img, keyword, name, type) VALUES (1, 1, 'http://www.jpj', '衣服', '阿迪促銷', 1);
INSERT INTO missyou.banner_item (id, banner_id, img, keyword, name, type) VALUES (2, 1, 'http://www.jpj', '鞋', '阿迪促銷', 1);
2、新建Controller\service\repository
BannerRepository倉儲層,主要負責讀取資料庫
@Repository
public interface BannerRepository extends JpaRepository<Banner, Long> {
Banner findOneById(Long id);
Banner findOneByName(String name);
}
sevice層,具體的業務邏輯
@Service
public class BannerServiceImpl implements BannerService{
@Autowired
private BannerRepository bannerRepository;
@Override
public Banner getByName(String name) {
return bannerRepository.findOneByName(name);
}
}
controller層,負責接收客戶端請求返回資料
@GetMapping("/banner/name/{name}")
public Banner getBannerByName(@PathVariable String name){
return bannerService.getByName(name);
}
請求介面:
可以看到資料已經查詢出來了。
- 雙向一對多
上面的示例是根據banner_id去查關聯的一組banner_item,但是有些場景我們可能需要通過某個item_id去查是屬於哪個banner,那這就是一種的反向的一對多,接下來我們看一下這總反向的一對多如何配置。
我們之前配置了一個items屬性
@OneToMany
@JoinColumn(name = "bannerId")
private List<BannerItem> items;
這個屬性就可以幫我們定位到某個banenr關聯的一組bannerItem,可以叫做導航屬性,那麼反過來,如何從一個item定位到一個Banner,怎麼設定導航屬性?
首先需要在BannerItem實體類裡面增加一個banner屬性,並使用如下註解進行標記
@ManyToOne
@JoinColumn(name = "bannerId")
private Banner banner;
修改Banner實體
@OneToMany(mappedBy = "banner")
private List<BannerItem> items;
這裡其實就是把@JoinColumn(name = "bannerId")移動到BannerItem裡面。並且在BanenrItem裡要刪除掉之前定義的外來鍵欄位bannerId。
這是因為在設定雙向一對多的關係時,會預設在banner_item表裡生成一個外來鍵,如果自己再寫一個就會造成重複,程式就會報錯。
那如果自己很想指定,也可以,進行如下配置
@ManyToOne
@JoinColumn(insertable = false, updatable = false, name = "bannerId")
private Banner banner;
總結
以上就是我們介紹的關於在spring-boot中如何進行實體間的單向一對多和雙向一對多的配置,關於要在實際專案如何使用哪一種方式,還是要結合自己的業務,一般不需要進行雙向的配置,而且一般都不會去設定物理外來鍵,後面我們再討論如何進行多對多的配置以及如何去除物理外來鍵。
歡迎大家去 我的部落格 瞅瞅,裡面有更多關於測試實戰的內容哦!!