对外键的Db约束

时间:2012-07-24 06:28:00

标签: android ormlite

我的帐户实体中有一个订单列表。因此,我的订单实体将外键返回到其父订单。什么是在首先保存其父帐户之前阻止保存订单的最佳方法。我不希望没有帐户的数据库中存在任何订单。 更好地解释 这是我的订单类

@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

3 个答案:

答案 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的

<?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>

最后是DbHandler类

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);
    }
}

实际上你不会手动添加订单号(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

答案 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,您可以使用它。