我的帐户实体中有一个订单列表。因此,我的订单实体将外键返回到其父订单。什么是在首先保存其父帐户之前阻止保存订单的最佳方法。我不希望没有帐户的数据库中存在任何订单。 更好地解释 这是我的订单类
@DatabaseTable
public class Order{
private static final long serialVersionUID = 1L;
@DatabaseField(id = true)
private long id;
@DatabaseField(foreign = true)
private Account account;
}
这是我的帐户类
@DatabaseTable
public class Account {
private static final long serialVersionUID = 1L;
@DatabaseField(id = true)
private int id;
@ForeignCollectionField
private ForeignCollection<Order> orders;
public ForeignCollection<Order> getOrders() {
return orders;
}
public void setOrders(ForeignCollection<Order> orders) {
this.orders = orders;
}
}
事情是我可以在没有设置帐户的情况下保存订单。有没有办法通过在订单的帐户字段中设置一些属性来防止这种情况? 我省略了一些代码,但我知道上面的关系工作正常,因为当我在每个订单中设置帐户字段时,我可以检索给定帐户A1的订单Or1,Or2,Or3 = A1
答案 0 :(得分:0)
我粘贴了测试数据库应用程序的完整源代码。这应该可以解决您的问题。
我有一个活动类,它将提供用于下订单和支持xml文件的UI,以及用于执行数据库操作的DbHandler类。
这是活动代码。
package com.test;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.sqlite.SQLiteConstraintException;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class TestActivity extends Activity implements OnClickListener{
private EditText accountId = null;
private EditText orderNumber = null;
private Button submit = null;
private DBHandler dbHandler = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupUiElementProperties();
dbHandler = new DBHandler(this);
}
private void setupUiElementProperties() {
accountId = (EditText)findViewById(R.id.accountEditText);
orderNumber = (EditText)findViewById(R.id.orderNoEditText);
submit = (Button)findViewById(R.id.submit);
submit.setOnClickListener(this);
}
public void onClick(View v) {
try {
dbHandler.placeOrder(Integer.parseInt(accountId.getText().toString().trim()),
Integer.parseInt(orderNumber.getText().toString().trim()));
showAlert("ORDER PLACED SUCCESSFULLY");
System.out.println("DONE..");
}catch (SQLiteConstraintException ex) {
System.out.println("SQLITE EXCEPTIOn: " + ex.getMessage());
showAlert("THIS ACCOUNT DOES NOT EXISTS");
}catch (Exception e) {
System.out.println("Exceptionn: " + e.getMessage());
}
}
private void showAlert(String message) {
new AlertDialog.Builder(TestActivity.this)
.setTitle("Alert")
.setMessage(message)
.setPositiveButton("ok", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dlg, int sumthin) {}
})
.show();
}
}
这是main.xml的 最后是DbHandler类 实际上你不会手动添加订单号(ORDER_DETAILS表)。该字段必须自动递增并输入数据库。 我在DbHandler中添加了insertAccount(),因为“Account”表没有任何条目。使用此方法,我将添加帐户ID为“1234”的帐户。 这应该是你的输出: 方案1
帐号:1234
订单号:453412 此条目将插入到数据库中,因为帐户ID 1234存在于ACCOUNT表中,并显示成功的更新警报。 方案2
帐户2343
订单号:14523 由于外键约束失败,因此不会接受此条目。因此,您将收到一条警告,说“此帐户不存在”。 我的数据库可能与您要求的不一样,但我希望这应该足以帮助您。 使用SQLITEBROWSER查看数据。 你的db文件应该在......... 转到文件资源管理器-----&gt;数据------&gt;数据------&gt; com.test -----&gt; TESTDATA.db <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/accountEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="10dp"
android:layout_toRightOf="@+id/accountNoLabel" android:inputType="number">
<requestFocus />
</EditText>
<TextView
android:id="@+id/accountNoLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/accountEditText"
android:layout_alignBottom="@+id/accountEditText"
android:layout_alignParentLeft="true"
android:text="Account Id" android:layout_marginLeft="5dp"/>
<EditText
android:id="@+id/orderNoEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/accountEditText"
android:layout_alignRight="@+id/accountEditText"
android:layout_below="@+id/accountEditText" android:inputType="number"/>
<TextView
android:id="@+id/orderLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/orderNoEditText"
android:layout_alignBottom="@+id/orderNoEditText"
android:layout_alignLeft="@+id/accountNoLabel"
android:text="Order No" />
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Submit" />
</RelativeLayout>
package com.test;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHandler extends SQLiteOpenHelper {
private SQLiteDatabase sqliteDatabaseInstance_ = null;
public DBHandler(Context context){
super(context, "TESTDATABASE.db", null, 1);
sqliteDatabaseInstance_ = getWritableDatabase();
sqliteDatabaseInstance_.execSQL("PRAGMA foreign_keys = ON;");
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL("CREATE TABLE ACCOUNT (accountId INTEGER PRIMARY KEY, name TEXT)");
insertAccount(1234, "xyz", db);
db.execSQL("CREATE TABLE ORDER_DETAILS (orderNo INTEGER, accountId INTEGER," +
"FOREIGN KEY (accountId) REFERENCES ACCOUNT(accountId))");
}catch (SQLiteConstraintException sqliteConstraintException) {
System.out.println("sqliteConstraintException: " + sqliteConstraintException.getMessage());
}catch (Exception e) {
System.out.println("Exception in DBHandler.onCreate: "+e.getMessage());
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
public void placeOrder(int accountNo, int orderNo) throws SQLiteConstraintException{
ContentValues cv = new ContentValues();
cv.put("accountId", accountNo);
cv.put("orderNo", orderNo);
sqliteDatabaseInstance_.insertOrThrow("ORDER_DETAILS", null, cv);
}
private void insertAccount(int accId, String accountHolderName, SQLiteDatabase db) {
ContentValues cv = new ContentValues();
System.out.println("db: " + db);
System.out.println("accountId: " + accId) ;
System.out.println("accountHolderName: " + accountHolderName);
cv.put("accountId", accId);
cv.put("name", accountHolderName);
db.insertOrThrow("ACCOUNT", null, cv);
}
}
答案 1 :(得分:0)
很抱歉延迟回答。有几件事要在这里尝试。
account
上的Order
字段应为canBeNull = false
,以确保已分配字段。
@DatabaseField(foreign = true, canBeNull = false)
private Account account;
如果您尝试插入Order
而不设置Account
,则会引发异常。但是,您可以将account
文件设置为 not 已插入数据库的Account
。解决这个问题的方法是使Account.id
字段成为Integer
对象(而不是int
原语),如果它还没有null
那么它将是// this is an Integer object so it is null if it has not been set
@DatabaseField(id = true)
private Integer id;
已经确定。
Account.id
然后,如果尚未设置Order
字段,则如果您使用Account
创建@DatabaseField(generatedId = true)
,则会引发异常。顺便说一句,听起来你可能想要Integer
,但orderDao.create(...)
字段也适用于此。
最后,如果您尝试创建Order
字段为account
的{{1}}或{{1},您还可以覆盖null
方法以引发异常} field为0。
account.id
答案 2 :(得分:-1)
@ user965895:我没有看到你有标记的ormlite。我不知道。我建议的代码是针对SQLite的。 Android附带内置轻量级数据库SQLite,您可以使用它。