SpringDataJDBC一對一/一對多關係實現
Spring Data JDBC一對一和一對多關係實現
Spring Data JDBC能夠支援DDD中聚合概念,實際支援ER中星型模型,在DDD中聚合根實體代表整體概念,對映到資料表中就是星型模型中的主表,整體和部分的關係一般是一對一和一對多關係,其中一代表整體這一方,不會存在多對一或多對多關係,因為整體只能有一個。
1:1關係
首先看看一對一關係,一對一關係體現在物件和資料表兩個方面,先看看你物件的一對一關係,假設有一個Order訂單,其中包含了對地址Address的一對一關係,Order程式碼如下:
@Table("ordersample") public class Order { @org.springframework.data.annotation.Id public Integer Id; //代表一對一的關係 public Address address;
..
}
Address的程式碼如下:
public class Address { @org.springframework.data.annotation.Id public Integer Id; public String street; public String zipcode; }
一對一關係中,物件的類中都必須有一個主鍵標識,如上面的Id,Order和Address都有一個唯一標識Id,註釋都是@org.springframework.data.annotation.Id,注意不是javax.persistence.Id,後者是JPA的主鍵標識。
那麼,對應的資料表結構應該怎樣呢?我們可以從執行出錯的資訊中一窺究竟。
先把倉儲介面寫好:
public interface OrderRepo extends CrudRepository<Order, Integer>
再寫好測試程式碼:
Order order = new Order(); Address address = new Address(); address.street = "a street"; address.zipcode = "123456789"; order.address = address; orderRepo.save(order);
試驗執行的時候會提示SQL出錯,資料表結構沒有建立:
Table "ORDERSAMPLE" not found; SQL statement:
INSERT INTO ordersample () VALUES () [42102-197]
Order對應的資料表ordersample沒有建立,注意這裡資料表名稱如果不指定ordersample,預設是order會引起衝突,order是保留名稱。
ordersample資料表主要是一個自增主鍵:
CREATE TABLE ordersample ( idInteger IDENTITY PRIMARY KEY, );
在application.properties填入配置:
logging.level.sql=true
database=h2 spring.datasource.schema=classpath*:schema.sql spring.h2.console.enabled=Debug
這裡需要匯入schema.sql用來建立資料表結構。將ordersample資料表結構SQL放入schema.sql即可。
再次執行測試程式:
Caused by: org.h2.jdbc.JdbcSQLException: Table "ADDRESS" not found; SQL statement:
INSERT INTO address (street, zipcode, ordersample) VALUES (?, ?, ?) [42102-197]
這裡SQL語句已經顯示Address對應的address資料表結構:
CREATE TABLE address ( idInteger IDENTITY PRIMARY KEY, ordersampleInteger, street VARCHAR(80), zipcode VARCHAR(80) );
這裡的id對應類Address中@Id標註的主鍵,street和zipcode也是對應類Address的欄位,比較特殊的是ordersample,這個顯然是一個代表關係的外來鍵,指向ordersample資料表,也就是說,資料表之間表達一對一關係的方式是通過外來鍵引用實現的。
1:N關係
假設訂單Order中存在OrderItem:
@Table("ordersample") public class Order { @org.springframework.data.annotation.Id public Integer Id; //1:1 public Address address; //1:N public Collection<OrderItem> items;
類Order中使用集合Collection表示多個OrderItem,OrderItem的程式碼:
public class OrderItem { public String productVO; public int qty; }
注意到,在1:N關係中,多方這裡無需使用@Id唯一主鍵,從DDD角度來看,OrderItem其實是一個值物件,值物件與實體的區別就是沒有唯一標識。OrderItem對應的資料表結構:
CREATE TABLE order_item ( ordersample_key Integer IDENTITY PRIMARY KEY, product_vo VARCHAR(80), qty INTEGER, ordersample INTEGER );
我們注意到,Spring Data JDBC預設使用ordersample_key作為order_item表的主鍵,因為OrderItem物件是值物件,但是資料表需要主鍵,因此使用ordersample_key,同時外來鍵ordersample指向同名的主表ordersample,這是資料表的1:N的方式。
ofollow,noindex" target="_blank">原始碼