Android Room - 자동 생성으로 삽입된 새 행의 ID 가져오기
룸 지속성 라이브러리를 사용하여 데이터베이스에 데이터를 삽입하는 방법은 다음과 같습니다.
엔티티:
@Entity
class User {
@PrimaryKey(autoGenerate = true)
public int id;
//...
}
데이터 액세스 개체:
@Dao
public interface UserDao{
@Insert(onConflict = IGNORE)
void insertUser(User user);
//...
}
별도의 select 쿼리를 작성하지 않고 위 메소드 자체로 삽입이 완료되면 User의 id를 반환하는 것이 가능합니까?
여기에 있는 문서(코드 스니펫 아래)를 기반으로 합니다.
주석이 달린 방법@Insert
주석이 반환할 수 있습니다.
long
싱글 인서트 작업용long[]
또는Long[]
또는List<Long>
다중 삽입 작업의 경우void
삽입된 ID에 대해 신경 쓰지 않는 경우
@Insert
함수가 반환될 수 있습니다.void
,long
,long[]
또는List<Long>
이것 좀 드셔보세요.
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(User user);
// Insert multiple items
@Insert(onConflict = OnConflictStrategy.REPLACE)
long[] insert(User... user);
@Insert로 표기된 설명서 함수에 따르면 rowId를 반환할 수 있습니다.
@Insert 메서드가 하나의 매개 변수만 수신하면 삽입된 항목에 대한 새 rowId인 long을 반환할 수 있습니다.매개 변수가 배열 또는 집합인 경우 대신 long[] 또는 List<Long>을 반환해야 합니다.
제가 가지고 있는 문제는 이것이 ID가 아닌 rowId를 반환한다는 것이고 저는 rowId를 사용하여 rowId를 얻는 방법을 아직 찾지 못했습니다.
편집: 이제 rowId에서 id를 가져오는 방법을 알게 되었습니다.다음은 SQL 명령입니다.
SELECT id FROM table_name WHERE rowid = :rowId
다음 스니플릿으로 행 ID를 가져옵니다.미래가 있는 실행자 서비스에서 호출 가능을 사용합니다.
private UserDao userDao;
private ExecutorService executorService;
public long insertUploadStatus(User user) {
Callable<Long> insertCallable = () -> userDao.insert(user);
long rowId = 0;
Future<Long> future = executorService.submit(insertCallable);
try {
rowId = future.get();
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return rowId;
}
호출 가능에 대한 자세한 내용은 Java Executor Service 튜토리얼을 참조하십시오.
문장이 성공적으로 작성된 경우 한 레코드에 대한 삽입 반환 값은 1입니다.
개체 목록을 삽입하려는 경우 다음과 같이 수행할 수 있습니다.
@Insert(onConflict = OnConflictStrategy.REPLACE)
public long[] addAll(List<Object> list);
Rx2로 실행합니다.
Observable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
return yourDao.addAll(list<Object>);
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
// the o will be Long[].size => numbers of inserted records.
}
});
Dao에서 삽입 쿼리가 반환됩니다.Long
즉, 삽입한 rowId입니다.
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(recipes: CookingRecipes): Long
모델(리포지토리) 클래스: (MVVM)
fun addRecipesData(cookingRecipes: CookingRecipes): Single<Long>? {
return Single.fromCallable<Long> { recipesDao.insertManual(cookingRecipes) }
}
ModelView 클래스에서: (MVVM) 일회용 단일 관찰자로 LiveData를 처리합니다.
작업 소스 참조: https://github.com/SupriyaNaveen/CookingRecipes
많은 어려움 끝에, 저는 이것을 해결할 수 있었습니다.MMVM 아키텍처를 사용하는 솔루션은 다음과 같습니다.
학생.kt
@Entity(tableName = "students")
data class Student(
@NotNull var name: String,
@NotNull var password: String,
var subject: String,
var email: String
) {
@PrimaryKey(autoGenerate = true)
var roll: Int = 0
}
학생 다오.kt
interface StudentDao {
@Insert
fun insertStudent(student: Student) : Long
}
학생 저장소.kt
class StudentRepository private constructor(private val studentDao: StudentDao)
{
fun getStudents() = studentDao.getStudents()
fun insertStudent(student: Student): Single<Long>? {
return Single.fromCallable(
Callable<Long> { studentDao.insertStudent(student) }
)
}
companion object {
// For Singleton instantiation
@Volatile private var instance: StudentRepository? = null
fun getInstance(studentDao: StudentDao) =
instance ?: synchronized(this) {
instance ?: StudentRepository(studentDao).also { instance = it }
}
}
}
학생 보기 모델.kt
class StudentViewModel (application: Application) : AndroidViewModel(application) {
var status = MutableLiveData<Boolean?>()
private var repository: StudentRepository = StudentRepository.getInstance( AppDatabase.getInstance(application).studentDao())
private val disposable = CompositeDisposable()
fun insertStudent(student: Student) {
disposable.add(
repository.insertStudent(student)
?.subscribeOn(Schedulers.newThread())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribeWith(object : DisposableSingleObserver<Long>() {
override fun onSuccess(newReturnId: Long?) {
Log.d("ViewModel Insert", newReturnId.toString())
status.postValue(true)
}
override fun onError(e: Throwable?) {
status.postValue(false)
}
})
)
}
}
단편에서:
class RegistrationFragment : Fragment() {
private lateinit var dataBinding : FragmentRegistrationBinding
private val viewModel: StudentViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initialiseStudent()
viewModel.status.observe(viewLifecycleOwner, Observer { status ->
status?.let {
if(it){
Toast.makeText(context , "Data Inserted Sucessfully" , Toast.LENGTH_LONG).show()
val action = RegistrationFragmentDirections.actionRegistrationFragmentToLoginFragment()
Navigation.findNavController(view).navigate(action)
} else
Toast.makeText(context , "Something went wrong" , Toast.LENGTH_LONG).show()
//Reset status value at first to prevent multitriggering
//and to be available to trigger action again
viewModel.status.value = null
//Display Toast or snackbar
}
})
}
fun initialiseStudent() {
var student = Student(name =dataBinding.edName.text.toString(),
password= dataBinding.edPassword.text.toString(),
subject = "",
email = dataBinding.edEmail.text.toString())
dataBinding.viewmodel = viewModel
dataBinding.student = student
}
}
데이터 바인딩을 사용했습니다.내 XML은 다음과 같습니다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="student"
type="com.kgandroid.studentsubject.data.Student" />
<variable
name="listener"
type="com.kgandroid.studentsubject.view.RegistrationClickListener" />
<variable
name="viewmodel"
type="com.kgandroid.studentsubject.viewmodel.StudentViewModel" />
</data>
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context="com.kgandroid.studentsubject.view.RegistrationFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constarintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:isScrollContainer="true">
<TextView
android:id="@+id/tvRoll"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:gravity="center_horizontal"
android:text="Roll : 1"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvRoll" />
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="Name:"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
app:layout_constraintBaseline_toBaselineOf="@+id/edName"
app:layout_constraintEnd_toStartOf="@+id/edName"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tvEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
app:layout_constraintBaseline_toBaselineOf="@+id/edEmail"
app:layout_constraintEnd_toStartOf="@+id/edEmail"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/edEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edName" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Password"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
app:layout_constraintBaseline_toBaselineOf="@+id/edPassword"
app:layout_constraintEnd_toStartOf="@+id/edPassword"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/edPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edEmail" />
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="32dp"
android:background="@color/colorPrimary"
android:text="REGISTER"
android:onClick="@{() -> viewmodel.insertStudent(student)}"
android:textColor="@android:color/background_light"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edPassword" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</layout>
룸 삽입 및 삭제 작업이 별도의 스레드에서 수행되어야 하므로 비동기 작업으로 이 작업을 수행하기 위해 많은 어려움을 겪었습니다.마침내 RxJava에서 관찰 가능한 단일 유형으로 이 작업을 수행할 수 있습니다.
다음은 rxjava에 대한 Gradle 종속성입니다.
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.0.3'
@Insert 메서드가 단일 매개 변수를 수신하면 삽입된 항목에 대한 새 rowId인 긴 값을 반환할 수 있습니다.여기에 링크 설명 입력
@Insert
suspend fun insert(myEntity: MyEntity):Long
언급URL : https://stackoverflow.com/questions/44364240/android-room-get-the-id-of-new-inserted-row-with-auto-generate
'programing' 카테고리의 다른 글
테이블스페이스 생성 및 삭제 Oracle (0) | 2023.08.06 |
---|---|
마시멜로의 스토리지 사용 권한 오류 (0) | 2023.08.06 |
MariaDB의 동적 피벗 테이블이 php에서 작동하지 않는 쿼리 (0) | 2023.08.06 |
Spring Boot API 게이트웨이에서 이름을 확인할 수 없습니다. (0) | 2023.08.06 |
pymysql을 사용하여 MySQL에 데이터 파일을 로드할 수 없음 - 파일을 찾을 수 없음 (0) | 2023.08.06 |