当前位置:网站首页>Jetpack - basic use of room
Jetpack - basic use of room
2022-06-13 06:25:00 【m0_ forty-seven million nine hundred and fourteen thousand one 】
Android use SQLite Store as a database , Common in the open source community ORM(Object Relational Mappi
ng) Library has ORMLite,GreenDAO etc. .Room Like other libraries , Also in SQLite A layer of encapsulation is provided on the .
One .Room Use
1.Room Important concepts
Entity: Entity class , It corresponds to a table structure of the database , Using annotations @Entity Mark .
Dao: Contains access to a series of ways to access the database , Using annotations @Dao Mark .
Database: Database holder , As the main access point for the underlying connection of data related to application persistence . Use
annotation @Database Mark , In addition, the following conditions must be met : The defined class must be a class inherited from RoomDatab
ase The abstract class of , In the annotation, you need to define the list of entity classes associated with the database . Contains an extract with no parameters
Like a method and returns a Dao object .
2.Room application
First, add dependencies
implementation "androidx.room:room-runtime:2.3.0"
annotationProcessor "androidx.room:room-compiler:2.3.0"
// Table name
@Entity(tableName = "student")
public class Student {
// Self increasing
@PrimaryKey(autoGenerate = true)
/**
* name Field names in the table
* typeAffinity Field type
*/
@ColumnInfo(name="id",typeAffinity = ColumnInfo.INTEGER)
public int id;
@ColumnInfo(name ="name",typeAffinity = ColumnInfo.TEXT)
public String name;
@ColumnInfo(name = "age",typeAffinity = ColumnInfo.INTEGER)
public int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(int id) {
this.id=id;
}
}
First write an entity class (Entity class ), This entity class is the table we will store in the database , Entity class fields are the same as the fields in the table A corresponding .
@Dao
public interface StudentDao {
// increase
@Insert
void insertStudent(Student... Student);
// Delete
@Delete
void deleteStudent(Student... Student);
// Change
@Update
void UpdateStudent(Student... Student);
// Full investigation
@Query("SELECT * FROM student")
List<Student> getAllStudent();
// Condition check
@Query("SELECT * FROM student WHERE id=:id")
List<Student> getAStudent(int id);
}
Defined here Dao class , Define several methods for adding, deleting, modifying, and querying operation tables .
/**
* entities Is an array to configure your entity class here
* version Database version number
* exportSchema A wrong file , This place is closed first
*/
@Database(entities = {Student.class},version = 1, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {
// Database name
private static final String DATABASE_NAME="my_db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.addMigrations()
.build();
return sMyDataBase;
}
// obtain Student object
public abstract StudentDao getStudentDao();
}
In this Database Class Room database .
public class MainActivity extends AppCompatActivity {
private StudentDao mStudentDao;
private StudentRecyclerViewAdapter mStudentRecyclerViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recycleView = findViewById(R.id.recycleView);
ArrayList<Student> students = new ArrayList<>();
mStudentRecyclerViewAdapter = new StudentRecyclerViewAdapter(students);
recycleView.setLayoutManager(new LinearLayoutManager(this));
recycleView.setAdapter(mStudentRecyclerViewAdapter);
MyDataBase myDataBase = MyDataBase.getMyDataBase(this);
mStudentDao = myDataBase.getStudentDao();
}
public void mInsert(View view) {
Student[] m={new Student("Jack",20),new Student("xiaohua",20)};
new InsertStudentTask(mStudentDao).execute(m);
}
class InsertStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public InsertStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.insertStudent(pStudents);
return null;
}
}
public void mDelete(View view) {
new DeleterStudentTask(mStudentDao).execute(new Student(2));
}
public void mUpdate(View view) {
new UpdateStudentTask(mStudentDao).execute(new Student(4,"xiaogang",21));
}
class DeleterStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public DeleterStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.deleteStudent(pStudents);
return null;
}
}
class UpdateStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public UpdateStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.UpdateStudent(pStudents);
return null;
}
}
public void mQuery(View view) {
new GetAllStudentTask(mStudentDao).execute();
}
class GetAllStudentTask extends AsyncTask<Void,Void,Void>{
private StudentDao mStudentDao;
public GetAllStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Void... pStudents) {
List<Student> allStudent = mStudentDao.getAllStudent();
mStudentRecyclerViewAdapter.setStudents(allStudent);
return null;
}
@Override
protected void onPostExecute(Void pVoid) {
super.onPostExecute(pVoid);
mStudentRecyclerViewAdapter.notifyDataSetChanged();
}
}
}
stay Activity Use in AsyncTask Reference addition, deletion, modification and query functions , Operating the database .
Demonstration effect :
2.Room+ViewModel+LiveData
// Table name
@Entity(tableName = "student")
public class Student {
// Self increasing
@PrimaryKey(autoGenerate = true)
/**
* name Field names in the table
* typeAffinity Field type
*/
@ColumnInfo(name="id",typeAffinity = ColumnInfo.INTEGER)
public int id;
@ColumnInfo(name ="name",typeAffinity = ColumnInfo.TEXT)
public String name;
@ColumnInfo(name = "age",typeAffinity = ColumnInfo.INTEGER)
public int age;
/* @ColumnInfo(name = "sex",typeAffinity = ColumnInfo.TEXT)
public String sex;
@ColumnInfo(name = "aa",typeAffinity = ColumnInfo.INTEGER)
public int aa;*/
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(int id) {
this.id=id;
}
}
@Dao
public interface StudentDao {
// insert
@Insert
void insertStudent(Student... Student);
// Delete
@Delete
void deleteStudent(Student... Student);
// Delete all
@Query("DELETE FROM student")
void deleteAllStudent();
// Change
@Update
void UpdateStudent(Student... Student);
// Full investigation
@Query("SELECT * FROM student")
LiveData<List<Student>> getAllStudent();
// Condition check
@Query("SELECT * FROM student WHERE id=:id")
List<Student> getAStudent(int id);
}
/**
* entities Is an array to configure your entity class here
* version Database version number
* exportSchema A wrong file , This place is closed first
*/
//Schema Files can be checked for errors
@Database(entities = {Student.class},version = 1, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(),
MyDataBase.class, DATABASE_NAME)
.build();
return sMyDataBase;
}
public abstract StudentDao getStudentDao();
}
public class StudentRepository {
private StudentDao mStudentDao;
public StudentRepository(Context pContext) {
if (mStudentDao==null){
MyDataBase myDataBase = MyDataBase.getMyDataBase(pContext);
mStudentDao= myDataBase.getStudentDao();
}
}
// increase
public void InsertStudent(Student... pStudents) {
new InsertStudentTask(mStudentDao).execute(pStudents);
}
class InsertStudentTask extends AsyncTask<Student,Void,Void> {
private StudentDao mStudentDao;
public InsertStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.insertStudent(pStudents);
return null;
}
}
// Delete
public void DeleterStudent(int id) {
new DeleterStudentTask(mStudentDao).execute(new Student(id));
}
// Delete all
public void DeleterAllStudent() {
new DeleterAllStudentTask(mStudentDao).execute();
}
// Change
public void UpdateStudentTask(Student pStudents) {
new UpdateStudentTask(mStudentDao).execute(new Student(pStudents.id,pStudents.name,pStudents.age));
}
// Check here for LiveData
public LiveData<List<Student>> selectStudent(Student... pStudents) {
return mStudentDao.getAllStudent();
}
class DeleterStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public DeleterStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.deleteStudent(pStudents);
return null;
}
}
class DeleterAllStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public DeleterAllStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.deleteAllStudent();
return null;
}
}
class UpdateStudentTask extends AsyncTask<Student,Void,Void>{
private StudentDao mStudentDao;
public UpdateStudentTask(StudentDao pStudentDao) {
mStudentDao = pStudentDao;
}
@Override
protected Void doInBackground(Student... pStudents) {
mStudentDao.UpdateStudent(pStudents);
return null;
}
}
}
In this class, the thread switching operation of adding, deleting, changing and querying functions of the operation database
public class MyViewModel extends AndroidViewModel {
private final StudentRepository mStudentRepository;
public MyViewModel(@NonNull Application application) {
super(application);
mStudentRepository = new StudentRepository(application);
}
public void InsertStudent(Student... pStudents) {
mStudentRepository.InsertStudent(pStudents);
}
public void DeleterStudent(int id) {
mStudentRepository.DeleterStudent(id);
}
public void DeleterAllStudent() {
mStudentRepository.DeleterAllStudent();
}
public void UpdateStudentTask(Student pStudents) {
mStudentRepository.UpdateStudentTask(new Student(pStudents.id,pStudents.name,pStudents.age));
}
public LiveData<List<Student>> selectStudent() {
return mStudentRepository.selectStudent();
}
}
ViewModel As an intermediate transition layer .
public class MainActivity extends AppCompatActivity {
private StudentDao mStudentDao;
private StudentRecyclerViewAdapter mStudentRecyclerViewAdapter;
private MyViewModel mViewModel;
private int p=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recycleView = findViewById(R.id.recycleView);
ArrayList<Student> students = new ArrayList<>();
mStudentRecyclerViewAdapter = new StudentRecyclerViewAdapter(students);
recycleView.setLayoutManager(new LinearLayoutManager(this));
recycleView.setAdapter(mStudentRecyclerViewAdapter);
mViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);
mViewModel.selectStudent().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(List<Student> pStudents) {
mStudentRecyclerViewAdapter.setStudents(pStudents);
mStudentRecyclerViewAdapter.notifyDataSetChanged();
}
});
}
public void mInsert(View view) {
Student[] m={new Student("Jack",20),new Student("xiaohua",20)};
mViewModel.InsertStudent(m);
}
public void mDelete(View view) {
// new DeleterStudentTask(mStudentDao).execute(new Student(2));
mViewModel.DeleterStudent(p++);
}
public void mUpdate(View view) {
mViewModel.UpdateStudentTask(new Student(4,"xiaogang",21));
}
public void mQuery(View view) {
mViewModel.DeleterAllStudent();
}
}
This use liveData Once the database is modified, it will immediately start to callback and update UI
Demonstration effect :
3.Room Database upgrade
Room1 l 2 edition .
/**
* entities Is an array to configure your entity class here
* version Database version number , Add... When upgrading 1
* exportSchema A wrong file , This place is closed first
*/
//Schema Files can be checked for errors
@Database(entities = {Student.class},version = 2, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.addMigrations(MIGRATION_1_2)
.build();
return sMyDataBase;
}
//ROOM Database upgrade method When you want to upgrade across levels (1 To 4, He will do it in sequence 1 To 4 How to upgrade ) He will also execute the upgrade method in sequence
static final Migration MIGRATION_1_2=new Migration(1,2){
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN sex INTEGER NOT NULL DEFAULT 1");
}
};
public abstract StudentDao getStudentDao();
}
Here we are 1 l 2 When , use Sql Statement adds a field , So the entity class has to be changed .
// Table name
@Entity(tableName = "student")
public class Student {
// Self increasing
@PrimaryKey(autoGenerate = true)
/**
* name Field names in the table
* typeAffinity Field type
*/
@ColumnInfo(name="id",typeAffinity = ColumnInfo.INTEGER)
public int id;
@ColumnInfo(name ="name",typeAffinity = ColumnInfo.TEXT)
public String name;
@ColumnInfo(name = "age",typeAffinity = ColumnInfo.INTEGER)
public int age;
// Upgraded version 2 New fields added after
@ColumnInfo(name = "sex",typeAffinity = ColumnInfo.INTEGER)
public int sex;
/* @ColumnInfo(name = "aa",typeAffinity = ColumnInfo.INTEGER)
public int aa;*/
// Parameter and property names must have the same name
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(int id) {
this.id=id;
}
}
Let's go back to 2 l 3, Other methods are the same as this .
/**
* entities Is an array to configure your entity class here
* version Database version number , Add... When upgrading 1
* exportSchema A wrong file , This place is closed first
*/
//Schema Files can be checked for errors
@Database(entities = {Student.class},version = 3, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.addMigrations(MIGRATION_1_2,MIGRATION_2_3)
.build();
return sMyDataBase;
}
//ROOM Database upgrade method When you want to upgrade across levels (1 To 4, He will do it in sequence 1 To 4 How to upgrade ) He will also execute the upgrade method in sequence
static final Migration MIGRATION_1_2=new Migration(1,2){
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN sex INTEGER NOT NULL DEFAULT 1");
}
};
static final Migration MIGRATION_2_3=new Migration(2,3){
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN interest INTEGER NOT NULL DEFAULT 1");
}
};
public abstract StudentDao getStudentDao();
}
Then change the entity class .
// Table name
@Entity(tableName = "student")
public class Student {
// Self increasing
@PrimaryKey(autoGenerate = true)
/**
* name Field names in the table
* typeAffinity Field type
*/
@ColumnInfo(name="id",typeAffinity = ColumnInfo.INTEGER)
public int id;
@ColumnInfo(name ="name",typeAffinity = ColumnInfo.TEXT)
public String name;
@ColumnInfo(name = "age",typeAffinity = ColumnInfo.INTEGER)
public int age;
@ColumnInfo(name = "sex",typeAffinity = ColumnInfo.INTEGER)
public int sex;
@ColumnInfo(name = "interest",typeAffinity = ColumnInfo.INTEGER)
public int interest;
// Parameter and property names must have the same name
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore //Room The database will not be initialized with this
public Student(int id) {
this.id=id;
}
}
In this way, the database version will be upgraded to 3 了 , Cross version upgrade is the same as what I wrote in my notes , Will be executed in ascending order 2 Upgrade function to the latest version .
4.Room abnormal
@Database(entities = {Student.class},version = 4, exportSchema = true)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.addMigrations(MIGRATION_1_2,MIGRATION_2_3/*,MIGRATION_3_4*/)
.fallbackToDestructiveMigration() // This method reports an error when upgrading the database ( It's not because of changing the table structure ) Calling this method can forcibly upgrade data, but the original saved data will be lost
.build();
return sMyDataBase;
}
//ROOM Database upgrade method When you want to upgrade across levels (1 To 4, He will do it in sequence 1 To 4 How to upgrade ) He will also execute the upgrade method in sequence
static final Migration MIGRATION_1_2=new Migration(1,2){
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN sex INTEGER NOT NULL DEFAULT 1");
}
};
static final Migration MIGRATION_2_3=new Migration(2,3){
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN interest INTEGER NOT NULL DEFAULT 1");
}
};
public abstract StudentDao getStudentDao();
}
Now I write the version number in the code as 4, But it didn't write 4 How to upgrade , This call fallbackToDestructiveMigraion function , You can avoid reporting errors , But the data will be cleared
5.Schema file
Room During each database upgrade , Will export a Schema file , This is a json File format , It contains the basic information of the database , With the document , The developer can know the previous changes of the database , It is very convenient for developers to troubleshoot problems .
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]// Specify database schema Export location
}
}
}
Now? gradle Configure this paragraph .
//Schema Files can be checked for errors
@Database(entities = {Student.class},version = 4, exportSchema = true)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.build();
return sMyDataBase;
}
public abstract StudentDao getStudentDao();
}
When creating a database, put exportSchema Property set to true, That's all right.
The file will be here .
6. by Room Save as default
First, build a database and insert several pieces of data in it , The field name and type should be the same as Room The database should correspond to .
Then copy the database file to assets Under the folder .
And then there is the definition Room Just reference the database .
//Schema Files can be checked for errors
@Database(entities = {Student.class},version = 4, exportSchema = true)
public abstract class MyDataBase extends RoomDatabase {
private static final String DATABASE_NAME= "my.db";
private static MyDataBase sMyDataBase;
// You cannot create your own constructor here
public static MyDataBase getMyDataBase(Context mContext){
if (sMyDataBase==null)
sMyDataBase = Room.databaseBuilder(mContext.getApplicationContext(), MyDataBase.class, DATABASE_NAME)
//.allowMainThreadQueries() This method can be called to operate the database in the main thread
.createFromAsset("prestudent.db") // Initial value of Fu Copy the values of other tables into this table
.build();
return sMyDataBase;
}
}
Demonstration effect
7.TypeConverters
A lot of times , Our entity class will have a layer of arrays , Then embed a data class similar to the following Json strand :
{
"data": [
{
"category": " Source code ",
"icon": "",
"id": 22,
"link": "https://www.androidos.net.cn/sourcecode",
"name": "androidos",
"order": 11,
"visible": 1
},
{
"category": " Source code ",
"icon": "",
"id": 41,
"link": "http://androidxref.com/",
"name": "androidxref",
"order": 12,
"visible": 1
}
],
"errorCode": 0,
"errorMsg": ""
}
At this time, we will use our TypeConverters 了 .
public class Department {
@ColumnInfo(name = "departmentId")
public int id;
@ColumnInfo(name = "departmentName")
public String name;
public Department() {
}
@Ignore
public Department(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Here are the nested classes in our inner layer , No table name is set .
public class BaseListConvert<T> {
@TypeConverter
public List<T> revert(String jsonString) {
// Use Gson Method to json Format string Turn into List
try {
Type type = new TypeToken<ArrayList<T>>(){}.getType();
List<T> list = new Gson().fromJson(jsonString,type);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@TypeConverter
public String converter(List<T> list) {
// Use Gson Method to List Turn into json Format string, It's easy for us to parse
return new Gson().toJson(list);
}
}
This is a tool class , There is no need to make any changes .
// Direct integration from BaseListConvert, Just pass in the type
public class DepartmentListConvert extends BaseListConvert<Department> {
}
Which generic on the right here , Your nested data classes when needed .
@Entity(tableName = "user") // Entity class creation needs to add @Entity annotation
// Here we will refer to the previously defined tool class
@TypeConverters({DepartmentListConvert.class})
public class User {
@PrimaryKey(autoGenerate = true)
@NonNull
public int id;
@ColumnInfo(name = "user_name")
public String userName;
@ColumnInfo(name = "user_age")
public int userAge;
@ColumnInfo(name = "user_mobile")
public String userMobile;
/**
* Single object only , No List/set
* Direct use @Embedded Embedded in user In the table , namely user The columns in the table will be based on Department Attribute increase of
*/
// @Embedded
// public Department department;
public List<Department> departments;
public User(/*int pId,*/ String userName, int userAge, String userMobile, List<Department> departments) {
/* id = pId;*/
this.userName = userName;
this.userAge = userAge;
this.userMobile = userMobile;
this.departments = departments;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", userAge=" + userAge +
", userMobile='" + userMobile + '\'' +
", departments=" + departments +
'}';
}
}
So it's done .
demo Address :RoomTest
边栏推荐
- Wechat applet: click the event to obtain the current device information (basic)
- JS convert text to language for playback
- Wechat applet (pull-down refresh data) novice to
- Adding classes dynamically in uni app
- Wechat applet uploads pictures (preview deletion limits the size and number of pictures)
- Detailed explanation of Yanghui triangle
- Echart矩形树图:简单实现矩形树图
- IOError(Errors.E050.format(name=name))
- Wechat applet: use of global state variables
- Free screen recording software captura download and installation
猜你喜欢
Echart柱状图:堆叠柱状图value格式化显示
【新手上路常见问答】关于技术管理
After clicking the uniapp e-commerce H5 embedded applet, the page prompts "the page iframe does not support referencing non business domain names"
二分查找
MFS详解(六)——MFS Chunk Server服务器安装与配置
SSM integration
JVM Foundation
欧姆龙平替国产大货—JY-V640半导体晶元盒读写器
Recommend a capacity expansion tool to completely solve the problem of insufficient disk space in Disk C and other disks
MFS詳解(七)——MFS客戶端與web監控安裝配置
随机推荐
欧姆龙平替国产大货—JY-V640半导体晶元盒读写器
Binary search
Analysis of 43 cases of MATLAB neural network: Chapter 10 classification of discrete Hopfield Neural Network -- evaluation of scientific research ability of colleges and Universities
杨辉三角形详解
[case] a super easy-to-use tool -- a calculator for programmers
[MySQL] basic knowledge review
How to view APK version number from apk
Wechat applet (pull-down refresh data) novice to
High burst solution 2
pthon 执行 pip 指令报错 You should consider upgrading via ...
Regular verification of mobile phone number, landline email ID card
本地文件秒搜工具 Everything
Intelligent digital asset management helps enterprises win the post epidemic Era
Uniapp secondary encapsulates uview components, and the parent component controls display and hiding
c语言对文件相关的处理和应用
[written examination questions of meituan]
A brief analysis of the overall process of view drawing
Time conversion'2015-04-20t11:12:00.000+0000 '
The title of the WebView page will be displayed in the top navigation bar of the app. How to customize
HBuilderX:HBuilderX安装以及其常用插件安装