Android SQLite数据库demo。架构组件Room

 Android架构组件Room

Room主要包含三个部分:

  • Database : 持有DB和DAO
  • Entity : 定义POJO类,即数据表结构
  • DAO(Data Access Objects) : 定义访问数据(增删改查)的接口
  • @Entity(tableName = "table_name**") 注解POJO类,定义数据表名称;
  • @PrimaryKey 定义主键,如果一个Entity使用的是复合主键,可以通过@Entity注解的primaryKeys 属性定义复合主键:@Entity(primaryKeys = {"firstName", "lastName"})
  • @ColumnInfo(name = “column_name”) 定义数据表中的字段名
  • @Ignore 用于告诉Room需要忽略的字段或方法
  • 建立索引:在@Entity注解的indices属性中添加索引字段。例如:indices = {@Index(value = {"first_name", "last_name"}, unique = true), ...}, unique = true可以确保表中不会出现{"first_name", "last_name"} 相同的数据。

 

1.2 Entitiy间的关系

不同于目前存在的大多数ORM库,Room不支持Entitiy对象间的直接引用。(具体原因可以参考: Understand why Room doesn't allow object references
但Room允许通过外键(Foreign Key)来表示Entity之间的关系。

 

@Entity(foreignKeys = @ForeignKey(entity = User.class,
                                  parentColumns = "id",
                                  childColumns = "user_id"))
class Book {
    @PrimaryKey
    public int bookId;

    public String title;

    @ColumnInfo(name = "user_id")
    public int userId;
}

如上面代码所示,Book对象与User对象是属于的关系。Book中的user_id,对应User中的id。 那么当一个User对象被删除时, 对应的Book会发生什么呢?

@ForeignKey注解中有两个属性onDeleteonUpdate, 这两个属性对应ForeignKey中的onDelete()onUpdate(), 通过这两个属性的值来设置当User对象被删除/更新时,Book对象作出的响应。这两个属性的可选值如下:

  • CASCADE:User删除时对应Book一同删除; 更新时,关联的字段一同更新
  • NO_ACTION:User删除时不做任何响应
  • RESTRICT:禁止User的删除/更新。当User删除或更新时,Sqlite会立马报错。
  • SET_NULL:当User删除时, Book中的userId会设为NULL
  • SET_DEFAULT:与SET_NULL类似,当User删除时,Book中的userId会设为默认值

2. 创建数据访问对象(DAO)

 

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND "
           + "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(List<User> users);
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);

    @Delete
    void delete(User user);
    
    @Update
    public void updateUsers(List<User> users);
}

DAO 可以是一个接口,也可以是一个抽象类, Room会在编译时创建DAO的实现。

 

2.2 查询参数传递

 

@Query("SELECT * FROM user WHERE uid IN (:userIds)")
List<User> loadAllByIds(int[] userIds);

@Query("SELECT * FROM user WHERE first_name LIKE :first AND "
           + "last_name LIKE :last LIMIT 1")
User findByName(String first, String last);

看代码应该比较好理解, 方法中传递参数arg, 在sql语句中用:arg即可。编译时R

2.3 查询表中部分字段的信息

在实际某个业务场景中, 我们可能仅关心一个表部分字段的值,这时我仅需要查询关心的列即可。

定义子集的POJO类:

 

public class NameTuple {
    @ColumnInfo(name="first_name")
    public String firstName;

    @ColumnInfo(name="last_name")
    public String lastName;
}

在DAO中添加查询方法:

 

@Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();

这里定义的POJO也支持使用@Embedded

2.4 联表查询

Room支持联表查询,接口定义上与其他查询差别不大, 主要还是sql语句的差别。

 

@Dao
public interface MyDao {
    @Query("SELECT * FROM book "
           + "INNER JOIN loan ON loan.book_id = book.id "
           + "INNER JOIN user ON user.id = loan.user_id "
           + "WHERE user.name LIKE :userName")
   public List<Book> findBooksBorrowedByNameSync(String userName);
}

2.4 联表查询

Room支持联表查询,接口定义上与其他查询差别不大, 主要还是sql语句的差别。

 

@Dao
public interface MyDao {
    @Query("SELECT * FROM book "
           + "INNER JOIN loan ON loan.book_id = book.id "
           + "INNER JOIN user ON user.id = loan.user_id "
           + "WHERE user.name LIKE :userName")
   public List<Book> findBooksBorrowedByNameSync(String userName);
}

Room提供了Migration类来实现数据库的升级:

 

Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
        .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                + "`name` TEXT, PRIMARY KEY(`id`))");
    }
};

static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE Book "
                + " ADD COLUMN pub_year INTEGER");
    }
};

在创建Migration类时需要指定startVersionendVersion, 代码中MIGRATION_1_2MIGRATION_2_3的startVersion和endVersion是递增的, Migration其实是支持从版本1直接升到版本3,只要其migrate()方法里执行的语句正常即可。那么Room是怎么实现数据库升级的呢?其实本质上还是调用SQLiteOpenHelper.onUpgrade,Room中自己实现了一个SQLiteOpenHelper, 在onUpgrade()方法被调用时触发Migration,当第一次访问数据库时,Room做了以下几件事:

  • 创建Room Database实例
  • SQLiteOpenHelper.onUpgrade被调用,并且触发Migration
  • 打开数据库

架构组件Room、demo了解:https://download.csdn.net/download/meixi_android/19386289

 

 

原生sqlite、demo链接:https://download.csdn.net/download/meixi_android/10710400

 

创建数据库版本v.1

/**
 * 作者:created by meixi
 * 邮箱:13164716840@163.com
 * 日期:2018/10/9 11
 */
public class DBHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "mall.db";
    private static final int DATABASE_VERSION = 1000;

    private static DBHelper instance = null;


    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public synchronized static DBHelper getInstance(Context context) {
        if (instance == null) {
            instance = new DBHelper(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL.CREATE_TABLE_FAVORITE);

        // 若不是第一个版本安装,直接执行数据库升级
        // 请不要修改FIRST_DATABASE_VERSION的值,其为第一个数据库版本大小
        final int FIRST_DATABASE_VERSION = 1000;
        onUpgrade(db, FIRST_DATABASE_VERSION, DATABASE_VERSION);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 使用for实现跨版本升级数据库
        for (int i = oldVersion; i < newVersion; i++) {
            switch (i) {

                default:
                    break;
            }
        }
    }
}

 

创建数据库语句:

public class SQL {
    public static final String T_FAVORITE = "favorite";


    public static final String CREATE_TABLE_FAVORITE =
            "CREATE TABLE IF NOT EXISTS " + T_FAVORITE + "(" +
                    "_id integer primary key autoincrement, " +
                    "title VARCHAR, " +
                    "url VARCHAR, " +
                    "createDate VARCHAR " +
                    ")";
}

实现增删改查activity:

public class MainActivity extends AppCompatActivity {

    private static String CREATE_TABLE ="create table number(_id integer primary key autoincrement ,phone real)";

    int ab  = 0,cd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1=findViewById(R.id.baocunid);
        Button button2=findViewById(R.id.duquid);
        Button button3=findViewById(R.id.shanchuid);
        Button button4=findViewById(R.id.xiugaiid);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ab++;
                boolean nn = baocun(MainActivity.this, new String[] { "114499title","rullll---htt;s=="+ab,"加入的xxx" });
                Log.i("lgq","sbbbb---"+nn);
            }
        });
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getBai(MainActivity.this);
            }
        });
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               String ss= Delete(MainActivity.this,"1");
                Log.i("lgq","shanchu=g==="+ss);
            }
        });
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String ss = updata(MainActivity.this,"");
                Log.i("lgq","xiugg=g==="+ss);
            }
        });
    }

    public static boolean baocun(Context context, String[] values) {
        SQLiteDatabase db2=null;
        DBHelper2 dbHelper = null;
        try {
            dbHelper =new DBHelper2(context);
            db2 = dbHelper.getWritableDatabase();
            db2=dbHelper.getWritableDatabase();
            db2.beginTransaction();
            db2.execSQL("insert into favorite (title,url,deleted) values (?,?,?)",values);
            db2.setTransactionSuccessful();
            db2.endTransaction();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }finally{

        }

    }

    public  List<String> getBai(Context context){
        List<String> list = new ArrayList<String>();
        SQLiteDatabase db2=null;
        DBHelper2 dbHelper = null;
        try {

            dbHelper= new DBHelper2(context);
            db2=dbHelper.getWritableDatabase();
            Cursor cursor =db2.rawQuery("select _id,title,deleted from favorite", null);
            while(cursor.moveToNext()){
                cd++;
//                int dbid = cursor.getInt(cursor.getColumnIndex("_id"));
                int id=cursor.getInt(cursor.getColumnIndex("_id"));
                String haoma = cursor.getString(cursor.getColumnIndex("title"))+"";
                String names = cursor.getString(cursor.getColumnIndex("deleted"));
                list.add(haoma);
                System.out.println("lgqs======"+haoma+"......."+names+"     "+cd+"    id===  "+id);
            }
            db2.setTransactionSuccessful();
            db2.endTransaction();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;

    }

    public static String Delete(Context context,String string){
        SQLiteDatabase db2=null;
        DBHelper2 dbHelper = null;
        try {
            dbHelper =new DBHelper2(context);
            db2 = dbHelper.getWritableDatabase();
            db2=dbHelper.getWritableDatabase();
            db2.beginTransaction();
            db2.execSQL("delete from favorite where _id=?",new String[] { string });
            db2.setTransactionSuccessful();
            db2.endTransaction();
            return "成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "失败";
        }
    }
    public static String updata(Context context,String string){
        SQLiteDatabase db2=null;
        DBHelper2 dbHelper = null;
        try {
            dbHelper =new DBHelper2(context);
            db2 = dbHelper.getWritableDatabase();
            db2=dbHelper.getWritableDatabase();
            db2.beginTransaction();
            db2.execSQL("update favorite set title ="+"2222999"+" where url =?",new String[]{"rullll---htt;s==3"});
            db2.setTransactionSuccessful();
            db2.endTransaction();
            return "成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "失败";
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值