简体   繁体   English

如何在 Room 2.3.0 中向我的实体添加外键?

[英]How do I add a foreign key to my entity in Room 2.3.0?

I have a project that I have worked with Room 2.2.5, I just updated to version 2.3.0 this is the code of an entity called photo:我有一个使用 Room 2.2.5 的项目,我刚刚更新到 2.3.0 版本,这是一个名为 photo 的实体的代码:

    @Entity(tableName = Photo.TABLE_NAME, foreignKeys = @ForeignKey(entity = Event.class,
        parentColumns = "_id",
        childColumns = "id_event_ft",
        onDelete = ForeignKey.CASCADE))
public class Photo {

    public static final String TABLE_NAME = "Photo";
    public static final String COLUMN_ID = BaseColumns._ID;

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(index = true, name = COLUMN_ID)
    public Long id_photo;

    @ColumnInfo(name = "path")
    private String path;

    @ForeignKey(entity = Event.class,
            parentColumns = "_id",
            childColumns = "id_event_ft",
            onDelete = ForeignKey.CASCADE)
    private Long id_event_ft;

    public Photo(Long id_photo, String path, Long id_event_ft) {
        this.id_photo = id_photo;
        this.path = path;
        this.id_event_ft = id_event_ft;
    }

    public Long getId_photo() {
        return id_photo;
    }

    public void setId_photo(Long id_photo) {
        this.id_photo = id_photo;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Long getId_event_ft() {
        return id_event_ft;
    }

    public void setId_event_ft(Long id_event_ft) {
        this.id_event_ft = id_event_ft;
    }
}

Now I am getting the following error when trying to compile现在我在尝试编译时收到以下错误

error: annotation type not applicable to this kind of declaration @ForeignKey(entity = Event.class, parentColumns = "_id", childColumns = "id_event_ft", onDelete = ForeignKey.CASCADE) ^错误:注释类型不适用于这种声明 @ForeignKey(entity = Event.class, parentColumns = "_id", childColumns = "id_event_ft", onDelete = ForeignKey.CASCADE) ^

The error is in the @ForeignKey that is above the variable private Long id_event_ft;错误出现在变量private Long id_event_ft;

In the documentation I found this:文档中我发现了这个:

Added missing target to @ForeignKey annotation preventing its usage outside of the @Entity annotation.向 @ForeignKey 注释添加了缺少的目标,以防止其在 @Entity 注释之外使用。 (Iced1e) (Iced1e)

It is clear that using @ForeignKey outside of the @Entity annotation is no longer allowed, but then how do I bind the id_event_ft variable to the foreign key?, How do I assign a value to it now?很明显,不再允许在 @Entity 注释之外使用 @ForeignKey ,但是我如何将id_event_ft变量绑定到外键?,我现在如何为其赋值?

I hope someone can help me, thank you very much我希望有人可以帮助我,非常感谢

Relations关系

@Many To One @多对一

if the relation is many photo for one event, use ORM Hibernate, this is the easiest way to define foreign key with constraint on your Photo Entity如果关系是一个事件的多张照片,请使用 ORM Hibernate,这是定义外键并限制照片实体的最简单方法

@ManyToOne
@JoinColumn(name = "id", nullable = false)
private Event id_event_ft;

Using ForeignKey does not automatically (magically) make a relationship.使用ForeignKey不会自动(神奇地)建立关系。 Rather it allows a relationship to be supported primarily by enforcing referential integrity.相反,它允许主要通过强制引用完整性来支持关系。

  • There is no need for a ForeignKey definition for a Foreign Key (relationship) to exist.外键(关系)的存在不需要外键定义。

That is it is defining a rule that says that the value of the child column ( id_event_ft ) MUST be a value that is present in the parent column ( _id ).也就是说,它定义了一条规则,即子列 ( id_event_ft ) 的值必须是父列 ( _id ) 中存在的值。 It also supports handling if there is a Foreign Key Conflict (eg onDelete as you have used).如果存在外键冲突,它还支持处理(例如您使用的onDelete )。

Actually providing a suitable value is something that you have to do programmatically, that is id adding a photo you have to determine which Event the photo is to be linked/related to.实际上,提供合适的值是您必须以编程方式执行的操作,即 id 添加照片,您必须确定照片要链接/相关的事件。

You can use @Relation to simplify extracting related data.您可以使用@Relation 来简化提取相关数据的过程。

So consider the following:所以考虑以下几点:

An Event Entity (nice and simple for demonstration)一个事件实体(很好而且简单的演示)

@Entity
public class Event {
    @PrimaryKey(autoGenerate = true)
    Long _id = null;
    String other_columns;

    public Event(){}
    @Ignore
    public Event(String other_columns) {
        this.other_columns = other_columns;
    }
}
  • A Photo's parent column will be the _id column.照片的父列将是_id列。
  • Second Ignored (ie Ignored by Room) constructor otherwise Room issue a warning like *warning: There are multiple good constructors and Room will pick the no-arg constructor. Second Ignored (ie Ignored by Room) 构造函数,否则 Room 会发出警告,如 *warning: There are multiple good constructors and Room 将选择无参数构造函数。 * *

A slightly changed Photo Entity:-稍微改变的照片实体:-

@Entity(tableName = Photo.TABLE_NAME,
        foreignKeys = @ForeignKey(
                entity = Event.class,
                parentColumns = "_id",
                childColumns = "id_event_ft",
                onDelete = ForeignKey.CASCADE),
        indices = @Index("id_event_ft") //<<<<<<<<<< ADDED as Room warns if omitted
)
public class Photo {

    public static final String TABLE_NAME = "Photo";
    public static final String COLUMN_ID = BaseColumns._ID;

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(index = true, name = COLUMN_ID)
    public Long id_photo;
    @ColumnInfo(name = "path")
    private String path;
    /* <<<<<<<< COMMENTED OUT >>>>>>>>>>
    @ForeignKey(entity = Event.class,
            parentColumns = "_id",
            childColumns = "id_event_ft",
            onDelete = ForeignKey.CASCADE)

     */
    private Long id_event_ft;

    public Photo(Long id_photo, String path, Long id_event_ft) {
        this.id_photo = id_photo;
        this.path = path;
        this.id_event_ft = id_event_ft;
    }

    public Long getId_photo() {
        return id_photo;
    }

    public void setId_photo(Long id_photo) {
        this.id_photo = id_photo;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Long getId_event_ft() {
        return id_event_ft;
    }

    public void setId_event_ft(Long id_event_ft) {
        this.id_event_ft = id_event_ft;
    }
}

For demonstration of retrieving via a relationship the POJO EventWithPhotos :-为了演示通过关系检索 POJO EventWithPhotos :-

public class EventWithPhotos {

    @Embedded
    Event event;
    @Relation(entity = Photo.class,parentColumn = "_id",entityColumn = "id_event_ft")
    List<Photo> photos;
}

Now a Dao AllDao :-现在是道AllDao :-

@Dao
interface AllDao {

    @Insert
    long insert(Event event);
    @Insert
    long insert(Photo photo);
    @Transaction
    @Query("SELECT * FROM event")
    List<EventWithPhotos> getAllEventsWithPhotos();
}

How do I assign a value to it now?我现在如何为其赋值?

Now an example that puts it all together adding 2 Events the first with 2 photos, the second with 1 photo.现在是一个将所有事件放在一起的示例,第一个事件有 2 张照片,第二个事件有 1 张照片。 Note the different techniques used:-请注意使用的不同技术:-

    dao = db.getAllDao();

    // Prepare to add an Event
    Event newEvent = new Event();
    newEvent.other_columns = "Event1";
    // Add the Event retrieving the id (_id column)
    long eventId = dao.insert(newEvent);
    // Prepare a photo to be added to Event1
    Photo newPhoto = new Photo(null,"photo1",eventId);
    // Add the Photo to Event1
    long photoid = dao.insert(newPhoto);
    // Add second photo to Event 1 using the 2nd constructor
    dao.insert(new Photo(null,"photo2",eventId));
    // Add Event2 with a photo all in a single line (again using the 2nd constrcutor)
    long event2Id;
    dao.insert(new Photo(null,"photo3",event2Id = dao.insert(new Event("Event2"))));

    // Get and output Each Event with the Photos for that Event
    List<EventWithPhotos> allEventsWithPhotosList = dao.getAllEventsWithPhotos();
    for (EventWithPhotos ewp: allEventsWithPhotosList) {
        Log.d("EVENTPHOTOINFO","Event is " + ewp.event.other_columns);
        for (Photo p: ewp.photos) {
            Log.d("EVENTWITHPHOTO","\tPhoto is " + p.getPath() + " ID is " + p.getId_photo());
        }
    }

Result结果

When run the log contains:-运行时日志包含:-

D/EVENTPHOTOINFO: Event is Event1
D/EVENTWITHPHOTO:   Photo is photo1 ID is 1
D/EVENTWITHPHOTO:   Photo is photo2 ID is 2
D/EVENTPHOTOINFO: Event is Event2
D/EVENTWITHPHOTO:   Photo is photo3 ID is 3

The Database (view with Database Inspector) shows:-数据库(使用数据库检查器查看)显示:-

The Event table:-事件表:-

在此处输入图像描述

The Photo table:-照片表:-

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM