[Android / Java] Operate a local database in Room

environment

Basic

--Create an entity class with @ Entity. --Create a class that operates entities with @Dao. --Create a class that inherits RoomDatabase and register the class with @ Dao as its member. --Operate a class that inherits RoomDatabase from the app

Note that classes that inherit from RoomDatabase cannot be operated on the main thread.

Example of @ Entity class

@Entity(indices = {@Index(value = {"name"}, unique = true)})
public class User {
	@PrimaryKey
	public long id;

	@ColumnInfo
	public String name;
}

@Dao class example

@Dao
public abstract class UserDao {
	@Query("select id from user order by id desc limit 1")
	public abstract long getMaxId();

	@Insert(onConflict = OnConflictStrategy.IGNORE)
	abstract void insert(User user);

	@Query("delete from user where id = :id")
	abstract void delete(long id);
}

RoomDatabase Inheritance class example

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
	public abstract UserDao userDao();
}

Example of a Singleton class that creates a DB instance

public class AppDatabaseSingleton {
	private static AppDatabase instance = null;
	private AppDatabaseSingleton() {}

	public static AppDatabase getInstance(Context context) {
		if (instance != null) {
			return instance;
		}
		instance =  Room.databaseBuilder(context,
				AppDatabase.class, "app_database").build();
		return instance;
	}
}

Database operation example

new Thread(new Runnable() {
	@Override
	public void run() {
		AppDatabase db = AppDatabaseSingleton.getInstance(context);
		long maxId = db.UserDao().getMaxId();
		callback.onComplete(maxId);
	}
}).start();

Specify the table name

Write in @ Entity like(tableName = {"table name"). If you do not specify it, the table will be created with the same name as the model name, so it is better to specify it if possible.

@Entity(tableName = "users")
public class User {
    @PrimaryKey
    public int id;

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

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

Create a column that you want to have in your model but not in your DB

Write @Ignore before the column name.

@Entity
public class User {
    @PrimaryKey
    public int id;

    public String firstName;
    public String lastName;

    @Ignore
    Bitmap picture;
}

Unique index to multiple columns

Write (indeces = {@Index (value = {"first column "," second column "}, unique = true)}) in @ Entity.

@Entity(indices = {@Index(value = {"first_name", "last_name"},
        unique = true)})
public class User {
    @PrimaryKey
    public int id;

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

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

I want to set multiple items at once

Write separated by commas

@Entity(tableName = "users",
        indices = {@Index(value = {"first_name", "last_name"},
        unique = true)})

I want to do something like INSERT IGNORE

First of all, as a basic thing, issue a query with @Dao instead of @Entity.

Add (onConflict = OnConflictStrategy.IGNORE) to @ Insert. If you want to replace it, use (onConflict = OnConflictStrategy.REPLACE).

@Dao
public interface MyDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public void insertUsers(User... users);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertBothUsers(User user1, User user2);

    @Insert
    public void insertUsersAndFriends(User user, List<User> friends);
}

I want to make a transaction

If you want to make a transaction, you need to change from ʻinterface to ʻabstract class. Then, specify @Transaction as the target method.

@Dao
abstract class UsersDao {
    @Transaction
    public void setLoggedInUser(User loggedInUser) {
        deleteUser(loggedInUser);
        insertUser(loggedInUser);
    }

    @Query("DELETE FROM users")
    abstract void deleteUser(User user);

    @Insert
    abstract void insertUser(User user);
}

I want to add more tables and columns later

Raise the version as in SQLite. If you just raise it, nothing will be done, so you need to write what to do. If you don't write it, you will get angry.

A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.

The error message kindly tells you what to do, so in short, just do it. For example, if you upgrade to version 3, add a Fruit table in version 2, and add a column of Integer called pub_year to the Book table in version 3, you get:

@Database(entities = {Fruit.class, Book.class}, version = 3)
public abstract class AppDatabase extends RoomDatabase {
	:
	public static AppDatabase getInstance(Context context) {
		if (instance != null) {
			return instance;
		}
		static final Migration MIGRATION_1_2 = new Migration(1, 2) {
			@Override
			public void migrate(@NonNull 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(@NonNull SupportSQLiteDatabase database) {
				database.execSQL("ALTER TABLE Book "
						+ " ADD COLUMN pub_year INTEGER");
			}
		};
		instance =  Room.databaseBuilder(context,
				AppDatabase.class, "database-name")
				.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
				.build();
		return instance;
	}
}

I'd like you to wrap this area well, but at the moment there is a sense of human power. It may be relatively easy to use the table creation SQL etc. as it is with reference to the expanded room. For example, if you have created an inherited class for RoomDatabase with the class name com.example.db.AppDatabase, then ʻapp / build / generated / source / apt / debug / com / example / db / AppDatabase_Impl.java The contents expanded to are output. The following is an example of ʻAppDatabase_Impl.

@SuppressWarnings({"unchecked", "deprecation"})
public final class AppDatabase_Impl extends AppDatabase {
  @Override
  protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
    final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(2) {
      @Override
      public void createAllTables(SupportSQLiteDatabase _db) {
        _db.execSQL("CREATE TABLE IF NOT EXISTS `Fruit` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))");
        :
      }
      :
    }
  }
}

reference

Other

How to name Google's low googleability, what can I do ...

Recommended Posts

[Android / Java] Operate a local database in Room
I tried using a database connection in Android development
Find a subset in Java
Read WAV data as a byte array in Android Java
Try implementing Android Hilt in Java
3 Implement a simple interpreter in Java
I created a PDF in Java.
Create a database in a production environment
A simple sample callback in Java
Get stuck in a Java primer
Create a clear time ranking in Firebase's Realtime Database (Android app)
How to automatically operate a screen created in Java on Windows
Determining if a custom keyboard is enabled in Android Studio (Java)
About returning a reference in a Java Getter
What is a class in Java language (3 /?)
When seeking multiple in a Java array
To create a Zip file while grouping database search results in Java
[Creating] A memorandum about coding in Java
Java creates a table in a Word document
Java creates a pie chart in Excel
What is a class in Java language (1 /?)
What is a class in Java language (2 /?)
Create a TODO app in Java 7 Create Header
Try making a calculator app in Java
Implement something like a stack in Java
Split a string with ". (Dot)" in Java
Creating a matrix class in Java Part 1
[Android Studio] Description that can be continuously input in SQLite Database [Java]
Java to C and C to Java in Android Studio
I made a primality test program in Java
GetInstance () from a @Singleton class in Groovy from Java
Two ways to start a thread in Java + @
Read a string in a PDF file with Java
A story about the JDK in the Java 11 era
How to display a web page in Java
Measure the size of a folder in Java
Code to escape a JSON string in Java
Try to create a bulletin board in Java
About var used in Java (Local Variable Type)
[Java] Use of final in local variable declaration
A note when you want Tuple in Java
I wanted to make (a == 1 && a == 2 && a == 3) true in Java
I wrote a primality test program in Java
Let's create a super-simple web framework in Java
Delete all records in a MySQL database table
I made a rock-paper-scissors game in Java (CLI)
A story about trying to operate JAVA File
A bat file that uses Java in windows
Java tips-Create a Spring Boot project in Gradle
A quick review of Java learned in class
I wrote a prime factorization program in Java
Represents "next day" and "previous day" in Java / Android
Partization in Java
Changes in Java 11
Rock-paper-scissors in Java
Pi in Java
Java local class
FizzBuzz in Java
[Android / Java] Screen transition and return processing in fragments
I made a simple calculation problem game in Java
How to create a Java environment in just 3 seconds