2017-08-12 100 views
1

請注意:我是新來發揮框架玩! Framework數據庫繼承

信息:

我一直在使用播放框架尋找一個體面的教程或有關繼承的解釋一兩個小時,

但是每個例子似乎都忽略了引起混淆的整個示例,因此也是這個問題的原因。

爲了記錄在案,我使用MariaDB的(又名〜MySQL的)

研究&文檔:

  • 文檔 - 玩:this是不是非常有幫助

  • 文檔 - Java:useful,缺少完整示例

  • #1:幾個問題,herehere

  • 博客:This缺乏完整的例子,雖然有見地

  • 搜索上Youtube,對於PlayFramework設立eBean有用。

不過,我可能只是完全misunderstandin,但所提供的例子加入不同的名字列到未提及。

問題/疑問:

我需要建立一個數據庫,利用繼承(即外鍵等),究竟如何,與解釋,我能做到嗎?

數據庫模式:

enter image description here

我有什麼目前:

型號:用戶

import io.ebean.Finder; 
import io.ebean.Model; 
import play.data.validation.Constraints; 

import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.MappedSuperclass; 

@MappedSuperclass 
//@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public class User extends Model { 

    @Id 
    @GeneratedValue 
    private Long userId; 

    @Constraints.MaxLength(50) 
    private String name; 
    @Constraints.MaxLength(100) 
    private String surname; 

    @Constraints.Required 
    @Constraints.MinLength(8) 
    private String password; 

    @Constraints.Email 
    @Constraints.Required 
    private String email; 

    @Constraints.Required 
    @Constraints.MaxLength(10) 
    @Constraints.MinLength(10) 
    @Constraints.Pattern("[0]\\d{2}[- ]{0,1}\\d{3}[- ]{0,1}\\d{4}") 
    private String cellNumber; 

    private Boolean emailVerified = false; 
    private String token; 

    public static Finder<String, User> find = new Finder<String, User>(User.class); 

    public User(){} 

    public User(@Constraints.MinLength(10) @Constraints.MaxLength(10) Long userId, String name, String surname, @Constraints.Required String password, @Constraints.Email @Constraints.Required String email, @Constraints.Required @Constraints.Pattern("[0]\\d{2}[- ]{0,1}\\d{3}[- ]{0,1}\\d{4}") String cellNumber, Boolean emailVerified) { 
     this.userId = userId; 
     this.name = name; 
     this.surname = surname; 
     this.password = password; 
     this.email = email; 
     this.cellNumber = cellNumber; 
     this.emailVerified = emailVerified; 
    } 

型號:員工

import io.ebean.Finder; 
import play.data.validation.Constraints; 

import javax.persistence.Entity; 
import javax.persistence.Id; 

/** 
* Created by cybex on 2017/07/13. 
*/ 

@Entity 
public class Staff extends User { 

    @Id 
    private Long userId; 

    @Constraints.Required 
    private Boolean isKitchenStaff; 

    public static Finder<String, Staff> find = new Finder<String, Staff>(Staff.class); 

    public Staff(@Constraints.Required Long userId, String name, String surname, @Constraints.Required String password, @Constraints.Email @Constraints.Required String email, @Constraints.Required @Constraints.Pattern("[0]\\d{2}[- ]{0,1}\\d{3}[- ]{0,1}\\d{4}") String cellNumber, String userId1, @Constraints.Required Boolean isKitchenStaff) { 
     super(userId, name, surname, password, email, cellNumber, false); 
     this.isKitchenStaff = isKitchenStaff; 
    } 
} 

型號:客戶

import io.ebean.Finder; 
import play.data.validation.Constraints; 
import javax.persistence.Entity; 

@Entity 
public class Customer extends User { 

    @Constraints.Required 
    private Address address; 
    private Boolean isStudent = false; 

    public Customer(){} 

    public Customer(Long userId, String name, String surname, String email, String cellNumber, String password, String userId1, @Constraints.Required Address address, Boolean isStudent) { 
     /*super(userId, name, surname, email, cellNumber, password, false);*/ 
     this.address = address; 
     this.isStudent = isStudent; 
    } 

    public static final Finder<String, Customer> find = new Finder<String, Customer>(Customer.class); 
} 

型號:地址

import io.ebean.Finder; 
import io.ebean.Model; 
import play.data.validation.Constraints; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 

/** 
* Created by cybex on 2017/07/13. 
*/ 

// TODO: 2017/07/13 Add fields for suburb and city for larger projects 
@Entity 
public class Address extends Model { 

    @Id 
    @Constraints.Required 
    @GeneratedValue 
    @Constraints.Max(15) 
    private Long addressId; 
    @Constraints.Required 
    private String unitNumber; 
    @Constraints.Required 
    private String streetName; 
    private String communityName; 
    private Boolean isCommunity; 

    public Address(@Constraints.Required Long addressId, @Constraints.Required String unitNumber, @Constraints.Required String streetName, String communityName, Boolean isCommunity) { 
     this.addressId = addressId; 
     this.unitNumber = unitNumber; 
     this.streetName = streetName; 
     this.communityName = communityName; 
     this.isCommunity = isCommunity; 
    } 

    public static Finder<String, Address> find = new Finder<String, Address>(Address.class); 
} 

建議是增加:

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 

但是它導致一個錯誤:

CreationException: Unable to create injector, see the following errors: 

1) Error injecting constructor, java.lang.NullPointerException 

看到here完全堆棧跟蹤

問題(和TL; DR):

TL; DR:基本功能齊全,具有解釋相關,播放!表示上述數據庫模式的框架模型。

回答

1

繼承類型不支持(如08月18日的,2017年)

Play使用Ebean ORM,目前不支持InheritanceType.TABLE_PER_CLASSInheritanceType.JOINED。這是一個突出的問題listed here

我已經驗證。我複製了你的代碼並用InheritanceType.TABLE_PER_CLASS運行它。 Play創建了用戶和地址表,但不創建子表,員工和客戶。

僅供參考,擺脫錯誤的...

Error injecting constructor, java.lang.NullPointerException 

...你需要給@Entity註釋添加到用戶,與InheritanceType一起:

@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public class User extends Model { 
... 

對於爲了完成,你還需要刪除...

private Long userId; 

...從工作人員,因爲它是繼承自用戶。


你有什麼選擇?

1)您可以將您的項目重組爲use hibernate with Play,它支持InheritanceType.TABLE_PER_CLASSInheritanceType.JOINED

2)使用InheritanceType.SINGLE_TABLE。此方法將用戶,客戶和工作人員數據存儲在一個表中,用戶。它可能不是你理想的實現,但它會工作:

如果你決定在此,請注意...

The single table strategy maps all entities of the inheritance structure to the same database table. This approach makes polymorphic queries very efficient and provides the best performance.

But it also has some drawbacks. The attributes of all entities are mapped to the same database table. Each record uses only a subset of the available columns and sets the rest of them to null. You can, therefore, not use not null constraints on any column that isn’t mapped to all entities. That can create data integrity issues, and your database administrator might not be too happy about it. more on Inheritance Type comparisons

型號:用戶

import javax.persistence.DiscriminatorColumn; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.Inheritance; 
import javax.persistence.InheritanceType; 

import com.avaje.ebean.Model; 

import play.data.validation.Constraints; 

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "user_type") 
public class User extends Model { 

    @Id 
    @GeneratedValue 
    private Long userId; 

    @Constraints.MaxLength(50) 
    private String name; 
    @Constraints.MaxLength(100) 
    private String surname; 

    @Constraints.Required 
    @Constraints.MinLength(8) 
    private String password; 

    @Constraints.Email 
    @Constraints.Required 
    private String email; 

    @Constraints.Required 
    @Constraints.MaxLength(10) 
    @Constraints.MinLength(10) 
    @Constraints.Pattern("[0]\\d{2}[- ]{0,1}\\d{3}[- ]{0,1}\\d{4}") 
    private String cellNumber; 

    private Boolean emailVerified = false; 
    private String token; 

    public static Finder<String, User> find = new Finder<String, User>(User.class); 

    public User(){} 

} 

@DiscriminatorColumn(name = "user_type")是你如何區分一個記錄。 user_type值將爲null爲用戶記錄,客戶爲客戶記錄,員工爲員工記錄。

型號:員工

import javax.persistence.DiscriminatorValue; 
import javax.persistence.Entity; 

import play.data.validation.Constraints; 

@Entity 
@DiscriminatorValue("staff") 
public class Staff extends User { 

    @Constraints.Required 
    private Boolean isKitchenStaff; 

    public static Finder<String, Staff> find = new Finder<String, Staff>(Staff.class); 

    public Staff() {} 
} 

模型需求:

import javax.persistence.DiscriminatorValue; 
import javax.persistence.Entity; 
import javax.persistence.OneToOne; 

import play.data.validation.Constraints; 

@Entity 
@DiscriminatorValue("customer") 
public class Customer extends User { 

    @Constraints.Required 
    @OneToOne(mappedBy = "customer") 
    private Address address; 
    private Boolean isStudent = false; 

    public Customer(){} 

    public static final Finder<String, Customer> find = new Finder<String, Customer>(Customer.class); 
} 

@OneToOne地址映射添加到客戶。

型號地址:

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.OneToOne; 

import com.avaje.ebean.Model; 

import play.data.validation.Constraints; 

@Entity 
public class Address extends Model { 

    @Id 
    @Constraints.Required 
    @GeneratedValue 
    @Constraints.Max(15) 
    private Long addressId; 
    @Constraints.Required 
    private String unitNumber; 
    @Constraints.Required 
    private String streetName; 
    private String communityName; 
    private Boolean isCommunity; 

    @OneToOne 
    @JoinColumn(name = "user_id") 
    private Customer customer; 

    public Address(){} 

    public static Finder<String, Address> find = new Finder<String, Address>(Address.class); 
} 

@OneToOne客戶映射添加到地址。

這使用Play 2.5.10進行驗證。