@Entity
public class Agent {
@PrimaryKey
public String guid;
public String name;
public String email;
public String password;
public String phone;
public String licence;
}
@Dao
public interface AgentDao {
@Query("SELECT COUNT(*) FROM Agent where email = :email OR phone = :phone OR licence = :licence")
int agentsCount(String email, String phone, String licence);
@Insert
void insertAgent(Agent agent);
}
@Database(entities = {Agent.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract AgentDao agentDao();
}
class MyApp : Application() {
companion object DatabaseSetup {
var database: AppDatabase? = null
}
override fun onCreate() {
super.onCreate()
MyApp.database = Room.databaseBuilder(this, AppDatabase::class.java, "MyDatabase").build()
}
}
在“我的活动”中实现了以下功能:
void signUpAction(View view) {
String email = editTextEmail.getText().toString();
String phone = editTextPhone.getText().toString();
String license = editTextLicence.getText().toString();
AgentDao agentDao = MyApp.DatabaseSetup.getDatabase().agentDao();
//1: Check if agent already exists
int agentsCount = agentDao.agentsCount(email, phone, license);
if (agentsCount > 0) {
//2: If it already exists then prompt user
Toast.makeText(this, "Agent already exists!", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(this, "Agent does not exist! Hurray :)", Toast.LENGTH_LONG).show();
onBackPressed();
}
}
不幸的是,在执行上面的方法时,它会与下面的堆栈跟踪崩溃:
FATAL EXCEPTION: main
Process: com.example.me.MyApp, PID: 31592
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22288)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22288)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long periods of time.
at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:137)
at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:165)
at com.example.me.MyApp.RoomDb.Dao.AgentDao_Impl.agentsCount(AgentDao_Impl.java:94)
at com.example.me.MyApp.View.SignUpActivity.signUpAction(SignUpActivity.java:58)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22288)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
这个问题似乎与主线程上db操作的执行有关。但是,上面链接中提供的示例测试代码并不在单独的线程上运行:
@Test
public void writeUserAndReadInList() throws Exception {
User user = TestUtil.createUser(3);
user.setName("george");
mUserDao.insert(user);
List<User> byName = mUserDao.findUsersByName("george");
assertThat(byName.get(0), equalTo(user));
}
就像Dale说的那样,主线程上的数据库访问锁定UI是错误的。
--编辑2--
既然很多人可能会碰到这个答案...现在最好的选择,一般来说,是Kotlin Coroutines。Room现在直接支持它(目前处于测试版)。https://kotlinlang.org/docs/reference/coroutines-overview.html https://developer.android.com/jetpack/androidx/releases/room#2.1.0-beta01
private static class AgentAsyncTask extends AsyncTask<Void, Void, Integer> {
//Prevent leak
private WeakReference<Activity> weakActivity;
private String email;
private String phone;
private String license;
public AgentAsyncTask(Activity activity, String email, String phone, String license) {
weakActivity = new WeakReference<>(activity);
this.email = email;
this.phone = phone;
this.license = license;
}
@Override
protected Integer doInBackground(Void... params) {
AgentDao agentDao = MyApp.DatabaseSetup.getDatabase().agentDao();
return agentDao.agentsCount(email, phone, license);
}
@Override
protected void onPostExecute(Integer agentsCount) {
Activity activity = weakActivity.get();
if(activity == null) {
return;
}
if (agentsCount > 0) {
//2: If it already exists then prompt user
Toast.makeText(activity, "Agent already exists!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Agent does not exist! Hurray :)", Toast.LENGTH_LONG).show();
activity.onBackPressed();
}
}
}
然后在signUpAction(View View)方法中执行它:
new AgentAsyncTask(this, email, phone, license).execute();
在某些情况下,您可能还希望在活动中保留对AgentAsyncTask的引用,以便在活动被销毁时取消它。但您必须自己中断任何事务。
另外,你关于谷歌测试示例的问题...他们在网页上说:
我得到了一个著名的错误但根据我的理解,我没有访问主线程中的数据库,因为我正在执行由ThreadPoolExecutor执行的Runnable中的调用。我做错了什么? 在下面的方法中,我使用runnable从网络获取数据并将其存储在本地数据库中。 数据源.保存: 执行人定义为:
问题内容: 嗨,我有一个带有日期字段和一些其他信息的表。我想选择过去一周(从星期日开始的一周)中的所有条目。 表值: 我想选择上周的所有ID,预期输出为5、6、8 (ID 2不在上周,ID 15在本周。) 怎么写和SQL Query相同。 问题答案:
问题内容: 我有一张桌子,上面有我所有顾客购买的东西。我想选择上周(从周日开始的一周)中的所有条目。 我已经试过了: 但是我得到了上周的数据,包括本周的数据,我只想要上周的数据。 如何只获取上周的数据? 问题答案: 此条件将返回上周日至周六的记录: 有一个例子: 在对@ d456的回答中: 在间隔的两端不使用星期日的午夜吗? 没错,包括间隔两端的周日午夜。要在间隔结束时排除周日的午夜,必须使用运算
问题内容: 我有一个大约有110.000.000项的大型mysql表 表设计为: 现在我要查询一个普通查询: Explain语句给我: 该查询似乎很慢(约185秒),但我不知道这是否仅是由于表中的项目数量所致。您是否提示我如何加快查询或查表的速度? 问题答案: 我通常都同意Drap,但是以下查询变体可能更加有效,尤其是对于更大的LIMIT: 要求和索引。
我有几年没写SQL查询了,有点生疏。我正在尝试编写一个查询,该查询将根据给定的演员姓名选择所有影片。因此,给出名称“Sandra”,我想选择film表中的影片,该影片在actor表的first_name或last_name中有“Sandra”。有一个film_actor表将这两个表链接起来,但我不知道如何正确地实现它。我得到的最接近的是,它返回演员和影片的INNER JOIN表。这个结果还有一个f
这是运行命令后发生的情况: 启动:pid=4346 port=27017 dbpath=/var/lib/mongodb/data/db 64位host=era-inspiron-5559 2017-02-12T14:39:18.644+0530 I CONTROL[initandlisten]db版本v3.4.2 2017-02-12T14:39:18.644+0530 I控件[initandl