Android Room: Insert Relation Entities Using Room

How to insert entities with a one to many relationship in Room

There isn't a way that I am aware of that lets you directly insert a compound entity (like ShoppingListWithItems). You have to just insert the individual entities to their tables.

In your example, you would want to define an insert method for your ShoppingList entity which returns the generated primary key (so you can use it for your other items) and an insert method for your Item entities which can insert a whole list of them.

@Insert
suspend fun addNewShoppingList(newShoppingList: ShoppingList): Long
@Insert
suspend fun addNewItems(newItems: List<Item>)

Then you can run a transaction to insert them in a batch.

@Transaction
suspend fun addNewShoppingListWithItems(shoppingList: ShoppingList, items: List<Item>) {

val listId = addNewShoppingList(shoppingList)

items.forEach { it.parentListId = listId }
addNewItems(items)
}

Insert relation in Room android

Yes have ProductListProducts however you may wish to consider using :-

@Entity(
primaryKeys = ["productId", "productListId"]
,indices = [
Index(value = ["productListId"]) /* Index else Room warns */
]
/* Foreign Keys are optional BUT enforce referential integrity */
, foreignKeys = [
ForeignKey(
entity = Product::class,
parentColumns = ["productId"],
childColumns = ["productId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = ProductList::class,
parentColumns = ["productListId"],
childColumns = ["productListId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class ProductListProducts(
val productId: Long,
val productListId: Long
)
  • you may wish to refer to https://sqlite.org/foreignkeys.html

This is an associative table (reference table, mapping table and many other terms). So you use a Relationship that utilises the association for the Junction between the ProductList and Product. Therefore your ProductListWithProducts POJO becomes :-

data class ProductListWithProducts (
@Embedded
val productList: ProductList,
@Relation(
entity = Product::class,
parentColumn = "productListId",
entityColumn = "productId",
associateBy = Junction(
ProductListProducts::class,
parentColumn = "productListId",
entityColumn = "productId"
)
)
val product: List<Product>
)

Demonstration using the above classes (and your classes where the id's have been altered to be Long=0)

With a Dao class like :-

@Dao
abstract class AllDao {
@Insert
abstract fun insert(product: Product): Long
@Insert
abstract fun insert(productList: ProductList): Long
@Insert
abstract fun insert(productListProducts: ProductListProducts): Long
@Transaction
@Query("SELECT * FROM ProductList")
abstract fun getProductListWithProducts(): List<ProductListWithProducts>
}

Then the following (run on the main thread for brevity/convenience) :-

    db = TheDatabase.getInstance(this)
dao = db.getAllDao()

var p1 = dao.insert(Product( productName = "Product1"))
var p2 = dao.insert(Product(productName = "Product2"))
var pl1 = dao.insert(ProductList(listName = "List1"))
var pl2 = dao.insert(ProductList(listName = "List2"))
dao.insert(ProductListProducts(p1,pl1))
dao.insert(ProductListProducts(p1,pl2))
dao.insert(ProductListProducts(p2,pl1))

dao.insert(ProductListProducts(dao.insert(Product(productName = "Product3")),dao.insert(
ProductList(listName = "List3")))
)
for(plwp: ProductListWithProducts in dao.getProductListWithProducts()) {
Log.d(TAG,"ProductList is ${plwp.productList.listName} ID is ${plwp.productList.productListId}")
for(p: Product in plwp.product) {
Log.d(TAG,"\t Product is ${p.productName} ID is ${p.productId}")
}
}

results in the log containing :-

D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3

Can I add this relation without creating many-to-many relation, just one-to-many?

The above (i.e. the associative table) will handle 1 to many but if you don't want the the extra table then you would have to include the identifier of the parent in the child. You could enforce 1-many, in the associative table, by making the column for the 1 unique.

As for Mass type insertions you say

For example I already added Products in its table and after it want to create new ProductList

Then you could perhaps go about by having the following additional @Dao's :-

@Insert
abstract fun insert(productListList: List<ProductList>): LongArray
@Insert
abstract fun insertManyProductListProducts(productListProductsList: List<ProductListProducts>): LongArray

/* This can be used to get a specific product or products according to a pattern */
/* e.g. */
/* if productPatterName is product1 then an exact match */
/* if prod% then all that start with prod */
/* if %prod all that end in prod */
/* if %prod% then all that have prod anywhere */
@Query("SELECT productId FROM products WHERE productName LIKE :productNamePattern")
abstract fun getProductIdByName(productNamePattern: String): LongArray

And then have code such as :-

    /* Adding many new ProductLists to existing Products */
/* 1 add the new ProductLists */
/* Noting that the insert returns an array of the productListId's inserted */
val insertedProductLists = dao.insert(
listOf(
ProductList(listName = "ListX1"),
ProductList(listName = "ListX2")
)
)
/* 2. Determine the Product(s) that will be related to the new list of ProductLists */
val productIdList = dao.getProductIdByName("Product%") /* All products */
/* 3. Prepare the List of ProductListProducts for mass insertion */
val plplist: ArrayList<ProductListProducts> = ArrayList()
for(pid: Long in productIdList) {
for(plid: Long in insertedProductLists) {
plplist.add(ProductListProducts(pid,plid))
}
}
/* 4. add the relationships */
dao.insertManyProductListProducts(plplist)
  • If you wanted 1 existing product e.g. product1 then you would use dao.getProductIdByName("Product1"), of course you can also increase/reduce the productLists in the Array to suit.

This would result in :-

D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX1 ID is 4
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX2 ID is 5
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3

Room insert into one-to-many relationship

I'm assuming this cannot be done automatically, therefore we need a query to insert the parent, retrieve the ID for the parent and assign it to the child's foreign key, and then insert the child.

The first assumption is correct, that is that you have to supply the id of the parent (otherwise how is to know the parent).

However the second assumption that you have to query the parent is not always the case and not so in the scenario you describe. If when inserting a parent then the id is returned if using the convenience @Insert as a Long or an array of Longs (if inserting multiple Parents).

For example, say you have :-

@Entity
data class Parent(
@PrimaryKey
var id: Long? = null,
var other: String
)

and

@Entity
data class Child(
@PrimaryKey
var id: Long? = null,
var parentId: Long,
var otherdata: String
)

and an @Dao annotated class with :-

@Insert
fun insert(parent: Parent): Long
@Insert
fun insert(child: Child): Long

Then you can use the following, without having to query the Parent:-

    var lastParent = dao.insert(Parent(other = "Parent1 other data"))
dao.insert(Child(parentId = lastParent, otherdata = "Child1 other data"))
dao.insert(Child(parentId = lastParent, otherdata = "Child2 other data"))

// Insert a Child with it's Parent together
dao.insert(Child(
parentId = dao.insert(Parent(other = "Parent2 other data")),
otherdata = "Child3 other data"
))
  • note even if you define the id's as Int, a Long is returned when inserting.
    • It is incorrect to use Int for an id as SQLite stores the id as a 64bit signed integer which is to large for an Int.
      • However, issues would not occur until the id reached a value that is too large for an Int (32bit signed) i.e. greater than 2,147,483,647.

Room many to many relation is not working

But I am getting a strange behavior which is working till the first step, but not working for the relations.

You appear to have a strange schema, which may be the cause. That is you appear to have 2 relationships between Account's and Channel's.

On the Channel Entity you appear to have a Channel as a child to a single Account, as per AccountWithChannelsAndVpubs which includes:-

@Relation(
entity = ChannelEntity.class,
parentColumn = "accId",
entityColumn = "accountId"
)

That is the accountId in the ChannelEntity maps/references the Account.

However, in AccountWithChannels you have a mapping table for a many-many relationship between Channel and Account as per :-

@Relation(
parentColumn = "accId",
entityColumn = "channelId",
associateBy = @Junction(AccountChannelCrossRef.class)
)

Although this could be made to work, it could result in great confusion and perhaps that confusion is the result.

But the Vpub list is always returned as 0.

As you are using primitives (int) for id's then these default to 0, so perhaps you are inserting as per the default and hence the 0.

I tried with foreign also but not helped.

I assume you mean by defining ForeignKeys, perhaps they didn't help because they indicated issues (e.g. 0 in a cross reference table would result in a ForeignKey conflict).

In essence you code appears to work. Here's an equivalent based upon your code. Noting :-

  • I always use Long for id's (where generated) as:-

    • @Insert returns a Long
    • In theory problems could result if using Int or int for large databases.
  • For convenience/brevity code is run tested on the main thread.

  • For brevity getters and setters have been omitted.

  • Class member variables have been made private for classes that were created as they were not in the question, or changed to suit.

The testing/demo code:-

AccountEntity

@Entity
class AccountEntity {
@PrimaryKey
private Long accId;
private String accName;

public AccountEntity() {}

@Ignore
public AccountEntity(String accountName) {
this.accName = accountName;
}
}

ChannelEntity

@Entity
class ChannelEntity {
@PrimaryKey
private Long channelId;
private String channelName;
private long accountId;

public ChannelEntity(){}

@Ignore
public ChannelEntity(String channelName, long accountId) {

this.channelName = channelName;
this.accountId = accountId;
}
}

VPubEntity

@Entity
class VPubEntity {
@PrimaryKey
private Long vPubId;
private String vPubName;

public VPubEntity(){}

@Ignore
public VPubEntity(String vPubName) {
this.vPubName = vPubName;
}
}

AccountChannelCrossref

@Entity(
primaryKeys = {"accId","channelId"}
)
class AccountChannelCrossRef {
private long accId;
private long channelId;

public AccountChannelCrossRef(){}

@Ignore
public AccountChannelCrossRef(long accId, long channelId) {
this.accId = accId;
this.channelId = channelId;
}
}

ChannelVpubCrossRef (changed from int to long)

@Entity(
primaryKeys = {"channelId", "vPubId"}
)
public class ChannelVpubCrossRef {
public long channelId;
public long vPubId;
}

Classes ChannelWithVpubs, AccountWithChannels and AccountWithChannelsAndVpubs were copied as is and thus have not been inclduded.

A single @Dao annotated class was used as per :-

@Dao
abstract class AllDao {

@Insert
abstract long insert(AccountEntity accountEntity);
@Insert
abstract long insert(ChannelEntity channelEntity);
@Insert
abstract long insert(VPubEntity vPubEntity);
@Insert
abstract long insert(AccountChannelCrossRef accountChannelCrossRef);
@Insert
abstract long insert(ChannelVpubCrossRef channelVpubCrossRef);

@Query("INSERT INTO accountchannelcrossref VALUES(:accId,:channelId)")
abstract long insertAccountChannelCrossRef(long accId, long channelId);
@Query("INSERT INTO channelvpubcrossref VALUES(:channelId,:vPubId)")
abstract long insertChannelVPubCrossRef(long channelId,long vPubId);

@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void insertAccountList(List<AccountEntity> data);

@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void insertChannelList(List<ChannelEntity> data);

@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void insertVPubList(List<VPubEntity> data);

@Transaction
@Query("SELECT * FROM AccountEntity")
//public abstract LiveData<AccountWithChannelsAndVpubs> getAccountWithChannelsAndVpubs();
public abstract List<AccountWithChannelsAndVpubs> getAccountWithChannelsAndVpubs();
}

The @Database class was TheDatabase as per :-

@Database(
entities = {
AccountEntity.class,
ChannelEntity.class,
VPubEntity.class,
AccountChannelCrossRef.class,ChannelVpubCrossRef.class
},
version = 1
)
abstract class TheDatabase extends RoomDatabase {

abstract AllDao getAllDao();

private static volatile TheDatabase instance = null;
public static TheDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase.class,
"my.db"
)
.allowMainThreadQueries()
.build();
}
return instance;
}
}

Finally running the above was done using the following :-

public class MainActivity extends AppCompatActivity {

TheDatabase db;
AllDao dao;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

db = TheDatabase.getInstance(this);
dao = db.getAllDao();

long a1 = dao.insert(new AccountEntity("Account1"));
long a2 = dao.insert(new AccountEntity("Account2"));
long a3 = dao.insert(new AccountEntity("Account3"));

long c1 = dao.insert(new ChannelEntity("Channel1",a1)); //???? N2M 1 channel Many accounts
long c2 = dao.insert(new ChannelEntity("Channel2",a2));
long c3 = dao.insert(new ChannelEntity("Channel3",a3));

long v1 = dao.insert(new VPubEntity("VPub1"));
long v2 = dao.insert(new VPubEntity("VPub2"));
long v3 = dao.insert(new VPubEntity("VPub3"));

// ???? M2M between account and channel
dao.insert(new AccountChannelCrossRef(a1,c1));
dao.insert(new AccountChannelCrossRef(a1,c3));
dao.insert(new AccountChannelCrossRef(a2,c2));
dao.insert(new AccountChannelCrossRef(a3,c1));
dao.insert(new AccountChannelCrossRef(a3,c2));
dao.insert(new AccountChannelCrossRef(a3,c3));

ChannelVpubCrossRef cvxref1 = new ChannelVpubCrossRef();
cvxref1.channelId = c1;
cvxref1.vPubId = v1;
dao.insert(cvxref1);
cvxref1.vPubId = v2;
dao.insert(cvxref1);
cvxref1.vPubId = v3;
dao.insert(cvxref1);
cvxref1.channelId = c2;
cvxref1.vPubId = v3;
dao.insert(cvxref1);

String TAG = "AWCAVINFO";
for(AccountWithChannelsAndVpubs awcav: dao.getAccountWithChannelsAndVpubs()) {
Log.d(TAG,"Account is " + awcav.account.getAccName());
for (ChannelWithVpubs cwv: awcav.channelWithVpubs) {
Log.d(TAG,"\tChannel is " + cwv.channel.getChannelName());
for(VPubEntity v: cwv.vPubs) {
Log.d(TAG,"\t\tVPub is " + v.getVPubName());
}
}
}
}
}

Result (output to the log) :-

D/AWCAVINFO: Account is Account1
D/AWCAVINFO: Channel is Channel1
D/AWCAVINFO: VPub is VPub1
D/AWCAVINFO: VPub is VPub2
D/AWCAVINFO: VPub is VPub3
D/AWCAVINFO: Account is Account2
D/AWCAVINFO: Channel is Channel2
D/AWCAVINFO: VPub is VPub3
D/AWCAVINFO: Account is Account3
D/AWCAVINFO: Channel is Channel3

So the VPub's are extracted if there are any and hence why I suspect that your issue is not in the code that you have included in your question.

Android: how to insert data in manyToMany relationship in Room (Java)

First you should amend the Dao's so that they return the id of the inserted row enabling you to ascertain the actual id of the inserted rows. So :-

@Insert(onConflict = OnConflictStrategy.REPLACE)
public long insertCard(Card card);

@Insert(onConflict = OnConflictStrategy.REPLACE)
public long insertTag(Tag tag);

@Insert(onConflict = OnConflictStrategy.REPLACE)
public long insertCardWithTags(CardTagCrossRef cardTagCrossRef);

This allows you to retrieve the respective id when you insert either a Card or a Tag (note that for a CardTagCrossRef insertion this will be the rowid, a normally hidden row).

So you could then have use long cardId = cardDAO.insertCard(card.getCard()); and not then need to attempt to use cardTagCrossRef.idCard = card.getCard().getIdCard(); where the card DOES NOT have the id of the inserted card (part of the issue you are facing).

And likewise for the Tag.

So you could use :-

    long cardId = cardDAO.insertCard(card.getCard());
for (Tag t: card.getTagList()) {
long tagId = cardDAO.insertTag(t);
CardTagCrossRef cardTagCrossRef = new CardTagCrossRef();
cardTagCrossRef.idCard = cardId;
cardTagCrossRef.idTag = tagId;
Log.d(TAG, "CardCrossRef:" + cardTagCrossRef.idCard + cardTagCrossRef.idTag);
cardDAO.insertCardWithTags(cardTagCrossRef);
}

However, with a few changes I believe that that can make things far more flexible and have an insert that effectively does what you want within the Dao's.

SO perhaps consider the following that culminates in a working DEMO

Card

@Entity
public class Card {

@PrimaryKey/*(autoGenerate = true) SUGGESTED suppression of autogenerate as will still autogenerate but more efficiently */
private Long idCard;

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

@ColumnInfo(name = "taboo_word_1")
private String tabooWord1;

@ColumnInfo(name = "taboo_word_2")
private String tabooWord2;

@ColumnInfo(name = "taboo_word_3")
private String tabooWord3;

@ColumnInfo(name = "taboo_word_4")
private String tabooWord4;

@ColumnInfo(name = "taboo_word_5")
private String tabooWord5;

/* Constructors added */
public Card(){}

@Ignore
public Card(Long idCard,String title, String tabooWord1, String tabooWord2, String tabooWord3, String tabooWord4, String tabooWord5) {
this.idCard = idCard;
this.title = title;
this.tabooWord1 = tabooWord1;
this.tabooWord2 = tabooWord2;
this.tabooWord3 = tabooWord3;
this.tabooWord4 = tabooWord4;
this.tabooWord5 = tabooWord5;
}

public Long getIdCard() {
return idCard;
}

public void setIdCard(Long idCard) {
this.idCard = idCard;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getTabooWord1() {
return tabooWord1;
}

public void setTabooWord1(String tabooWord1) {
this.tabooWord1 = tabooWord1;
}

public String getTabooWord2() {
return tabooWord2;
}

public void setTabooWord2(String tabooWord2) {
this.tabooWord2 = tabooWord2;
}

public String getTabooWord3() {
return tabooWord3;
}

public void setTabooWord3(String tabooWord3) {
this.tabooWord3 = tabooWord3;
}

public String getTabooWord4() {
return tabooWord4;
}

public void setTabooWord4(String tabooWord4) {
this.tabooWord4 = tabooWord4;
}

public String getTabooWord5() {
return tabooWord5;
}

public void setTabooWord5(String tabooWord5) {
this.tabooWord5 = tabooWord5;
}
}
  • 2 changes an more flexible constructor and not using autogenerate = true (but that does automatically generate id's BUT without the overheads of the SQLite AUTOINCREMENT which is what autogenerate = true adds).

Tag (similar changes)

@Entity
public class Tag {

@PrimaryKey/*(autoGenerate = true) SUGGESTED suppression of autogenerate*/
private Long idTag;

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

public Tag(){}

@Ignore
public Tag(Long idTag, String tag) {
this.idTag = idTag;
this.tag = tag;
}

@Ignore
public Tag(String tag) {
this.tag = tag;
}

public Long getIdTag() {
return idTag;
}

public void setIdTag(Long idTag) {
this.idTag = idTag;
}

public String getTag() {
return tag;
}

public void setTag(String tag) {
this.tag = tag;
}

@Override
public String toString() {
return getTag();
}
}

CardTagCrossRef (added ForeignKey constraints to enforce/manage referential integrity)

@Entity(
primaryKeys = {"idCard", "idTag"}
/* SUGGESTED */
, foreignKeys = {
@ForeignKey(
entity = Card.class,
parentColumns = "idCard",
childColumns = "idCard",
/* SUGGESTED with ForeignKey */
onDelete = CASCADE,
onUpdate = CASCADE
),
@ForeignKey(
entity = Tag.class,
parentColumns = "idTag",
childColumns = "idTag",
/* SUGGESTED with ForeignKey */
onDelete = CASCADE,
onUpdate = CASCADE
)
}
)
public class CardTagCrossRef {

public long idCard;
@ColumnInfo(index = true) /* SUGGESTED */
public long idTag;

public CardTagCrossRef(){}
@Ignore
public CardTagCrossRef(long idCard, long idTag) {
this.idCard = idCard;
this.idTag = idTag;
}
}

CardWithTags

identical other than @Ignore annotation on the CardWithTags(Card card, List<Tag> tagList) constructor to supress warnings about multiple good consctructors.

i.e.

....
@Ignore /*<<<<< SUGGESTED */
public CardWithTags(Card card, List<Tag> tagList) {
this.card = card;
this.tagList = tagList;
}
....

CardDAO (new INSERT + return values)

@Dao
abstract class CardDAO {
/* public interface CardDAO { CHANGED TO abstract class to allow functions with bodies */

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract long insertCard(Card card); /* Returns long (inserted row id) */

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract long insertTag(Tag tag); /* Returns long (inserted row id) */

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract long insertCardWithTags(CardTagCrossRef cardTagCrossRef); /* Returns long (inserted row id) */

/* NEW INSERT */
@Query("")
@Transaction
long[] insert(Card card, List<Tag> tags) {
long[] rv = new long[tags.size() + 1];
int ix = 0;
rv[ix++] = insertCard(card);
if (rv[ix-1] > -1) {
for (Tag t : tags) {
rv[ix++] = insertTag(t);
if (rv[ix-1] > -1) {
insertCardWithTags(new CardTagCrossRef(rv[0],rv[ix-1]));
}
}

}
return rv;
}

// If called on an item not present in the DB it won't do anything
@Update
abstract int updateCard(Card card); /* returns number of updated rows */

@Delete
abstract int deleteCard(Card card); /* returns number of deleted rows */

// With a query method you can also perform complex inserts/updates/deletes
// Transaction needed for relational classes
@Transaction
@Query("SELECT * FROM Card")
/* abstract LiveData<List<CardWithTags>> getAllCards(); COMMENTED OUT to allow demo to run on main thread */
abstract List<CardWithTags> getAllCards(); /* same but not with LiveData */
}

DatabaseTaboom (allow main thread + exportSchema = false to suppress warning)

@Database(entities = {Card.class, Tag.class, CardTagCrossRef.class},
version = 1/* SUGGESTED */ , exportSchema = false)
public abstract class DatabaseTaboom extends RoomDatabase {

public static final String DATABASE_NAME = "db_taboom-1";
abstract CardDAO cardDao();
public static DatabaseTaboom db;

// Singleton pattern
public static DatabaseTaboom getDatabase(Context applicationContext) {
if (db == null) {
db = Room.databaseBuilder(applicationContext, DatabaseTaboom.class, DATABASE_NAME)
.allowMainThreadQueries() /* uncommented for testing */
.build();
}
return db;
}
}

Finally the DEMO MainActivity with some examples of inserting Cards, Tags and CardTagCrossRef's followed by extracting them all outputting the results to the log.

public class MainActivity extends AppCompatActivity {

DatabaseTaboom db;
CardDAO dao;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

db = DatabaseTaboom.getDatabase(this);
dao = db.cardDao();

/* Simple but long winded */
long c1id = dao.insertCard(new Card(null,"Card1","tw1","tw2","tw3","tw4","tw5"));
long t1id = dao.insertTag(new Tag(null,"TAG1"));
CardTagCrossRef ctcr1 = new CardTagCrossRef();
ctcr1.idCard = c1id;
ctcr1.idTag = t1id ;
dao.insertCardWithTags(ctcr1);
/* Using additional constructor for CardTagCrossRef */
long t2id = dao.insertTag(new Tag("TAG2"));
dao.insertCardWithTags(new CardTagCrossRef(c1id,t2id));
/* More dynamic BUT don't know the actual inserted id's of the Card and Tag */
dao.insertCardWithTags(
new CardTagCrossRef(dao.insertCard(new Card(100l,"Card2","c2tw1","c2tw2","c2tw3","c2tw4","c2tw5")),dao.insertTag(new Tag(null,"TAG3"))));


Related Topics



Leave a reply



Submit