Android GreenDao gives a comprehensive explanation on the use of Android GreenDao, and provides internal information of large manufacturers

Posted by Rumour on Fri, 17 Dec 2021 23:56:08 +0100

  1. github address of GreenDao
  2. Green Dao's Google discussion area
  3. GreenDao encrypted SQLCipher for Android official description address
  4. Documents used by GreenDao

The role of GreenDao?

Through GreenDao, we can operate the database more quickly. We can use a simple face object API to store, update, delete and query Java objects.

Advantages and disadvantages of GreenDao?

  1. High performance. The following is the official statistical chart of three ORM solutions: GreenDao, OrmLite and ActiveAndroid:

    [external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (IMG ibaio4c1-1630384555911)( https://user-gold-cdn.xitu.io/2019/10/21/16deedf171885eae?imageView2/0/w/1280/h/960/ignore -error/1)]

  2. Easy to use powerful API covering relationships and connections;

  3. Minimum memory consumption;

  4. Small library size (< 100kb) to maintain low construction time and avoid 65k method restrictions;

  5. Database encryption: greenDAO supports SQLCipher to ensure user data security;

3. Use of greendao

There are three core classes of GreenDao: daomaster, daosession and xxxdao. These three classes will be created automatically without writing them yourself!

  • DaoMaster: DaoMaster saves database objects (SQLiteDatabase) and manages DAO classes (not objects) for specific schemas. It has static methods to create tables or delete them. Its internal classes OpenHelper and DevOpenHelper are SQLiteOpenHelper implementations, which create schemas in SQLite database.

  • DaoSession: manages all available DAO objects for a specific pattern, which you can obtain using one of the getter methods. DaoSession also provides some general persistence methods, such as entity insertion, loading, update, refresh and deletion.

  • XXXDao: data access objects (DAO) persist and query entities. For each entity, greenDAO generates Dao. It has more persistence methods than DaoSession, such as count, loadAll and insertInTx.

  • Entities: persistent objects. Typically, an entity object represents a database row using standard Java properties (such as a POJO or JavaBean).

    [external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-7lmdb9kf-1630384555912)( https://user-gold-cdn.xitu.io/2019/10/21/16deedf1861dd3ce?imageView2/0/w/1280/h/960/ignore -error/1)]

1. Import Gradle plug-in and Dao code generation

To use GreenDao in an Android project, you need to add the GreenDao Gradle plug-in and add the GreenDao Library:

  1. Import plug-in
// In Project build Add to gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
} 
  1. Configure related dependencies
// In Moudle:app's build Add to gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // add library
} 
  1. Configuration database related information
greendao {
    schemaVersion 1 //Database version number
    daoPackage 'com.aserbao.aserbaosandroid.functions.database.greenDao.db'
// Set DaoMaster, DaoSession and Dao package names
    targetGenDir 'src/main/java'//Set DaoMaster, DaoSession and Dao directories. Please note that the path here is used / not used
    generateTests false //Set to true to automatically generate unit tests.
    targetGenDirTests 'src/main/java' //The base directory of the generated unit tests should be stored. The default is Src / Android test / Java.
} 

After the configuration is completed, use build > make project in Android Studio to rewrite the build project, and the GreenDao integration is completed!

2. Create storage object entity class

When using GreenDao to store data, you only need to declare @ Entity annotation in front of the stored data class to let GreenDao generate the necessary code for it:

@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Unique
    int studentNo;//Student number
    int age; //Age
    String telPhone;//cell-phone number
    String sex; //Gender
    String name;//full name
    String address;//Home address
    String schoolName;//School name
    String grade;//What grade
    ......getter and setter and constructor method......
    } 

3. GreenDao initialization

We can maintain a global session in the Application. We initialize the database in Applicaiton:

 /**
     * Initialize GreenDao directly in the Application
     */
    private void initGreenDao() {
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "aserbao.db");
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }
    
    private DaoSession daoSession;
    public DaoSession getDaoSession() {
        return daoSession;
    } 

After initialization, rebuild the project. You will find that three class files are generated in the set targetGenDir directory, which is automatically generated by GreenDao! It means that the database has been connected. Next, we only need to add, delete, modify and query the database. Let’s Go!

4. Use GreenDao to add, delete, modify and query

1. Increase

insert() insert data

 @Override
    public void insertData(Thing s) {
     DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
            for (int i = 0; i < 1000; i++) {
               Student student = new Student();
                        student.setStudentNo(i);
                        int age = mRandom.nextInt(10) + 10;
                        student.setAge(age);
                        student.setTelPhone(RandomValue.getTel());
                        String chineseName = RandomValue.getChineseName();
                        student.setName(chineseName);
                        if (i % 2 == 0) {
                            student.setSex("male");
                        } else {
                            student.setSex("female");
                        }
                        student.setAddress(RandomValue.getRoad());
                        student.setGrade(String.valueOf(age % 10) + "Age");
                        student.setSchoolName(RandomValue.getSchoolName());
                        daoSession.insert(student);
 			}
    } 

**insertOrReplace() * * replace if data exists, insert if data does not exist

@Override
    public void insertData(Thing s) {
    DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
            for (int i = 0; i < 1000; i++) {
                 Student student = new Student();
                        student.setStudentNo(i);
                        int age = mRandom.nextInt(10) + 10;
                        student.setAge(age);
                        student.setTelPhone(RandomValue.getTel());
                        String chineseName = RandomValue.getChineseName();
                        student.setName(chineseName);
                        if (i % 2 == 0) {
                            student.setSex("male");
                        } else {
                            student.setSex("female");
                        }
                        student.setAddress(RandomValue.getRoad());
                        student.setGrade(String.valueOf(age % 10) + "Age");
                        student.setSchoolName(RandomValue.getSchoolName());
                        daoSession.insertOrReplace(student);//Insert or replace
 			}
    } 

2. Delete

There are two ways to delete: delete() and deleteAll(); Delete single and delete all respectively.

 @Override
    public void deleteData(Student s) {
    	DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        daoSession.delete(s);
    } 

@Override
public void deleteAll() {
DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
daoSession.deleteAll(Student.class);
}

### 3\.  change

adopt update To modify:

@Override
public void updataData(Student s) {
DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
daoSession.update(s);
}

### 4\.  check

Query methods include:

*   loadAll(): Query all data.
*   queryRaw(): Query by criteria.
*   queryBuilder() : It is convenient to create queries, which will be explained in detail later.

public List queryAll(){
List students = daoSession.loadAll(Student.class);
return students;
}

 @Override
    public void queryData(String s) {
       List<Student> students = daoSession.queryRaw(Student.class, " where id = ?", s);
        mDataBaseAdapter.addNewStudentData(students);
    } 
```

4\. QueryBuilder Use of
===================

to write SQL It can be difficult and prone to errors that are only noticed at run time. Should QueryBuilder Classes allow you to create your entities without SQL Customize queries and help detect errors at compile time.

Let's talk about it first QueryBuilder Common methods of:

*   where(WhereCondition cond, WhereCondition... condMore): Query criteria. The parameter is the query criteria!
*   or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): Nested conditions or, the same as or. 
*   and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): Nested conditions, and the usage is the same as and. 
*   join(Property sourceProperty, Class destinationEntityClass):Multi table query, which will be described later. There are four ways to output results, one of which is the most suitable, list()The return value is List,The other three return values are implemented Closeable,Note: close the cursor when data is not used:
*   list ()All entities are loaded into memory. The result is usually one without magic ArrayList. Easiest to use.
*   listLazy ()Entities are loaded into memory on demand. When an element in the list is accessed for the first time, it is loaded and cached for future use. Must be closed.
*   listLazyUncached ()"Virtual" list of entities: any access to list elements causes its data to be loaded from the database. Must be closed.
*   listIterator ()Let's iterate over the results by loading data on demand (lazy). The data is not cached. It must be closed.
*   orderAsc() Sort by an attribute in ascending order;
*   orderDesc() Sort by a certain attribute in descending order;

GreenDao in SQL Statement abbreviation, we also understand that the source code is Property in,When using, you can click to query:

*   eq(): "equal ('=?')" be equal to;
*   notEq() : "not equal ('<>?')" Not equal to;
*   like(): " LIKE ?" Value equal to;
*   between(): " BETWEEN ? AND ?" Take the middle range;
*   in(): " IN (" in command;
*   notIn(): " NOT IN (" not in command;
*   gt(): ">?" greater than;
*   lt(): "<? " less than;
*   ge(): ">=?" Greater than or equal to;
*   le(): "<=? " Less than or equal to;
*   isNull(): " IS NULL" Empty;
*   isNotNull(): " IS NOT NULL" Not empty;

1\. use QueryBuilder Query operation
------------------------

### 1\.  Simple condition query

Query current Student All data in the table:

```
 public List queryAllList(){
  		DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> qb = daoSession.queryBuilder(Student.class);
        List<Student> list = qb.list(); // Find out all the data
	return list;
    } 
```

query Name For all of "one" Student:

```
 public List queryListByMessage(String name){
		 DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> qb = daoSession.queryBuilder(Student.class);
        QueryBuilder<Student> studentQueryBuilder = qb.where(StudentDao.Properties.Name.eq("one")).orderAsc(StudentDao.Properties.Name);
        List<Student> studentList = studentQueryBuilder.list(); //Find out the current corresponding data
        return list;
    } 
```

### 2\.  Original query

Through the original SQL Query by query statement! Actually, it's mentioned above QueryBuilder The purpose of is to write conveniently and quickly SQL Query statements to avoid our own mistakes in the writing process! A brief introduction is passed QueryBuilder Prepare the database as follows:

```
public List queryListBySqL(){
// Query all students with ID greater than 5
        DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        Query<Student> query = daoSession.queryBuilder(Student.class).where(
                new WhereCondition.StringCondition("_ID IN " +
                        "(SELECT _ID FROM STUDENT WHERE _ID > 5)")
        ).build();
        List<Student> list = query.list();
        return list;
    } 
```

### 3\.  Nested conditional query

query Id Greater than 5 but less than 10, and Name Value is"one"Data:

```
public List queryList(){
        DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> qb = daoSession.queryBuilder(Student.class);
        qb = daoSession.queryBuilder(Student.class);
        List<Student> list2 = qb.where(StudentDao.Properties.Name.eq("one"),
                qb.and(StudentDao.Properties.Id.gt(5),
                        StudentDao.Properties.Id.le(50))).list();
        return  list2;
    } 
```

Take 10 Id Data greater than 1 and offset by 2

```
 public List queryListByOther(){
        DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> qb = daoSession.queryBuilder(Student.class);

        //The search condition is that the Id value is greater than 1, that is, the result is [2,3,4,5,6,7,8,9,10,11];
        // offset(2) indicates two backward offsets, and the results are [4,5,6,7,8,9,10,11,12,13];
        List<Student> list = qb.where(StudentDao.Properties.Id.gt(1)).limit(10).offset(2).list();
        return list;
    } 
```

### 4\.  Find multiple times

use QueryBuilder After the query is built, it can be reused Query Object to execute the query later. This is better than always creating new ones Query Objects are more efficient. If the query parameters have not changed, you can call again list / unique method. Can pass setParameter Method to modify the condition parameter value:

```
 public List queryListByMoreTime(){
        DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> qb = daoSession.queryBuilder(Student.class);

        //The search condition is that the Id value is greater than 1, that is, the result is [2,3,4,5,6,7,8,9,10,11];
        // offset(2) indicates two backward offsets, and the results are [4,5,6,7,8,9,10,11,12,13];
        Query<Student> query = qb.where(StudentDao.Properties.Id.gt(1)).limit(10).offset(2).build();
        List<Student> list = query.list();
        
        //Use SetParameter to modify the above query criteria. For example, we modify the above criteria to take 10 pieces of data with Id value greater than 5 and offset two bits later. The method is as follows!
        query.setParameter(0,5);
        List<Student> list1 = query.list();
        return list1;
    } 
```

### 5\.  Using QueryBuilder in multiple threads

If you are using a query in multiple threads, you must call forCurrentThread ()To get the of the current thread Query example. Query The object instance of is bound to the owning thread that builds the query.

This allows you to safely Query Object without interference from other threads. If another thread tries to set parameters on a query or execute a query bound to another thread, an exception is thrown. Like this, you don't need to synchronize statements. In fact, you should avoid locking because if concurrent transactions use the same Query Object, which may cause deadlock.

Every call forCurrentThread ()When, the parameters are set as initial parameters when the query is built using its builder.

2\. use QueryBuilder Batch delete
--------------------------

use QueryBuilder Batch deletion will not delete a single entity, but will delete all entities that meet certain conditions. To perform a bulk delete, create QueryBuilder,Call its buildDelete ()Method, and then execute the returned DeleteQuery. 

Example: delete from database id All other data greater than 5

```
public boolean deleteItem(){
        DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
        QueryBuilder<Student> where = daoSession.queryBuilder(Student.class).where(StudentDao.Properties.Id.gt(5));
        DeleteQuery<Student> deleteQuery = where.buildDelete();
        deleteQuery.executeDeleteWithoutDetachingEntities();
        return false;
    } 
```

5\. Annotation explanation
========

from GreenDao 3 Annotations are used to define models and entities. As mentioned earlier, the use of annotations can quickly build database tables, including setting primary keys, self increment, whether values are unique, etc

Let's look at the simple use of annotations:

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Unique
    int studentNo;//Student number
    int age; //Age
    String telPhone;//cell-phone number
    String sex; //Gender
    String name;//full name
    String address;//Home address
    String schoolName;//School name
    String grade;//What grade
    ......getter and setter and constructor method......
    } 
```

1\. @Entity annotation
-------------

@Entity yes GreenDao The essential annotation is only used in entity classes@Entity annotation GreenDao The corresponding table will be created. Of course, we can also use@Entity Some details of configuration:

*   schema: If you have multiple architectures, you can tell GreenDao Which architecture does it currently belong to.
*   active: Mark an entity as active, and the active entity has update, delete and refresh methods.
*   nameInDb: The alias used in the data uses the class name of the entity by default.
*   indexes: Mark if DAO Database tables should be created(Default to true),If you have multiple entities mapped to a table, or the table is created in greenDAO Otherwise, set it to false. 
*   createInDb: Tag to create a database table.
*   generateGettersSetters: If it is missing, should the attribute be generated getter and setter method.

```
@Entity(

        schema = "myschema",
        active = true,
        nameInDb = "AWESOME_USERS",
        indexes = {
                @Index(value = "message DESC", unique = true)
        },
        createInDb = false,
        generateConstructors = true,
        generateGettersSetters = true
)
public class Student{	
	......
} 
```

2\. Basic attribute annotation(@Id,@Property,@NotNull,@Transient)
---------------------------------------------

**@Id** @Id Annotation selection long / Long Attribute as entity ID. On the database side, it is the primary key. parameter autoincrement = true Indicates self increasing, id Do not assign or assign null (note here that if you want to realize self increment, id Must be Long,by long no way!). 

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    ......
} 
```

**@Property** Allows you to define non default column names to which attributes are mapped. If it doesn't exist, GreenDAO Will take SQL-ish Use field names (uppercase, underline) instead of camel Situation, e.g name Will be NAME). Note: Currently, you can only use inline constants to specify column names.

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Property (nameInDb="name") //If set, the table attribute in the database is named "NAME". If not set, the table attribute in the database is named "NAME"
    String name;
    ......
} 
```

**@NotNull** : The current column of the set database table cannot be empty.

**@Transient** : After adding a secondary tag, the columns of the database table are not generated. Mark the attributes to exclude from persistence. Use them for temporary status, etc. Alternatively, you can use Java Medium transient keyword.

3\. Index annotation
--------

*   @Index: use@Index Create an index as an attribute through name You can also set the index alias through unique Add constraints to the index.
*   @Unique: Add to index UNIQUE Constraint that forces all values to be unique.

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Property(nameInDb="name")
    @Index(unique = true)
     String name;
    ......
} 
```

**be careful:** In this case, the agreement name Is a unique value, which is sent to the database through insert Method to continue adding an existing name Data, exception thrown:

```
10-08 20:59:46.274 31939-31939/com.example.aserbao.aserbaosandroid E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.aserbao.aserbaosandroid, PID: 31939
    android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: STUDENT.name (Sqlite code 2067), (OS error - 2:No such file or directory)
    ...... 
```

If used insertOrReplace()Method to add data. There will be no duplicate data in the current database, but the duplicate data id Will be modified! If useful in the project id This requires special attention when sorting fields.

4\. Relational annotation
--------

Relational annotation GreenDao There are mainly two aspects in the:

*   @ToOne: Defines a relationship with another entity (an entity object)
*   @ToMany: Define the relationship with multiple entity objects. As for how to use it, we'll talk about it right away.

6\. Creation of one-to-one, one to many, many to many relational tables
=====================

In ordinary projects, we often use multi table Association, such as the database table structure setting mentioned at the beginning of the article! Next, let's talk about how to pass GreenDao Implement multi table Association.

1\. one-on-one
-------

A student corresponds to an ID number.: Practice:

1.  We are Student Set an annotation in@ToOne(joinProperty = "name")
2.  Creating Student Transfer the corresponding data to IdCard; Code part:

student Student code:

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Unique
    int studentNo;//Student number
    int age; //Age
    String telPhone;//cell-phone number
    String sex; //Gender
    String name;//full name
    String address;//Home address
    String schoolName;//School name
    String grade;//What grade
    @ToOne(joinProperty = "name")
    IdCard student;
    ......getter and setter ......
} 
```

ID IdCard code:

```
@Entity
public class IdCard {
    @Id 
    String userName;//user name
    @Unique
    String idNo;//ID number
       ......getter and setter ......
} 
```

insert A set of data:

```
public void addStudent(){
						DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
 						Student student = new Student();
                        student.setStudentNo(i);
                        int age = mRandom.nextInt(10) + 10;
                        student.setAge(age);
                        student.setTelPhone(RandomValue.getTel());
                        String chineseName = RandomValue.getChineseName();
                        student.setName(chineseName);
                        if (i % 2 == 0) {
                            student.setSex("male");
                        } else {
                            student.setSex("female");
                        }
                        student.setAddress(RandomValue.getRoad());
                        student.setGrade(String.valueOf(age % 10) + "Age");
                        student.setSchoolName(RandomValue.getSchoolName());
                        daoSession.insert(student);
						
						//Insert the corresponding IdCard data
                        IdCard idCard = new IdCard();
				        idCard.setUserName(userName);
				        idCard.setIdNo(RandomValue.getRandomID());
				        daoSession.insert(idCard);
      } 
```

ok,The data is OK! The database table insertion is now complete.

2\. One to many
-------

One person has multiple credit cards:

1.  Yes, we are Student Medium setting@ToMany(referencedJoinProperty = "studentId");
2.  We are CreditCard Set the corresponding id Primary key;

Student Code of:

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;

    @Unique
    int studentNo;//Student number

    int age; //Age
    String telPhone;//cell-phone number
    String sex; //Gender
    String name;//full name
    String address;//Home address
    String schoolName;//School name
    String grade;//What grade
    
    @ToMany(referencedJoinProperty = "studentId) // This studentId corresponds to the studentId in the CreditCard
    List<CreditCard> creditCardsList;
      ......getter and setter ......
    } 
```

CreditCard Code of:

```
@Entity
public class CreditCard {
    @Id
    Long id;
    Long studentId;
    Long teacherId;
    String userName;//Holder name
    String cardNum;//Card number
    String whichBank;//Which bank
    int cardType;//Card level, classification 0 ~ 5
     ......getter and setter ......
    } 
```

Add data code:

```
public void addStudent(){
						DaoSession daoSession = ((AserbaoApplication) getApplication()).getDaoSession();
 						Student student = new Student();
                        student.setStudentNo(i);
                        int age = mRandom.nextInt(10) + 10;
                        student.setAge(age);
                        student.setTelPhone(RandomValue.getTel());
                        String chineseName = RandomValue.getChineseName();
                        student.setName(chineseName);
                        if (i % 2 == 0) {
                            student.setSex("male");
                        } else {
                            student.setSex("female");
                        }
                        student.setAddress(RandomValue.getRoad());
                        student.setGrade(String.valueOf(age % 10) + "Age");
                        student.setSchoolName(RandomValue.getSchoolName());
                        daoSession.insert(student);
						
						//Insert corresponding CreditCard data
                       for (int j = 0; j < random.nextInt(5) + 1 ; j++) {
			            CreditCard creditCard = new CreditCard();
			            creditCard.setUserId(id);
			            creditCard.setUserName(userName);
			            creditCard.setCardNum(String.valueOf(random.nextInt(899999999) + 100000000) + String.valueOf(random.nextInt(899999999) + 100000000));
			            creditCard.setWhichBank(RandomValue.getBankName());
			            creditCard.setCardType(random.nextInt(10));
			            daoSession.insert(creditCard);
			        }
      } 
```

3\. Many to many
-------

A student has more than one teacher, and a teacher has more than one student. Practice:

1.  We need to create a student teacher manager(StudentAndTeacherBean),Used to correspond to students and teachers ID;
    
2.  We need to add notes in the student object:
    
    @ToMany @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "studentId",targetProperty = "teacherId") List teacherList;
    
3.  We need to add notes in the teacher object:@ToMany
    
    @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "teacherId",targetProperty = "studentId") List studentList;
    

StudentAndTeacherBean code:

```
@Entity
public class StudentAndTeacherBean {
    @Id(autoincrement = true)
    Long id;
    Long studentId;//Student ID
    Long teacherId;//Teacher ID
    ......getter and setter ......
} 
```

Student code:

```
@Entity
public class Student {
    @Id(autoincrement = true)
    Long id;
    @Unique
    int studentNo;//Student number
    int age; //Age
    String telPhone;//cell-phone number
    String sex; //Gender
    String name;//full name
    String address;//Home address
    String schoolName;//School name
    String grade;//What grade
    @ToMany
    @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "studentId",targetProperty = "teacherId")
    List<Teacher> teacherList;
        ......getter and setter ......
    } 
```

Teacher code:

```
@Entity
public class Teacher {
    @Id(autoincrement = true)
    Long id;
    @Unique
    int teacherNo;//Employee number
    int age; //Age
    String sex; //Gender
    String telPhone;
    String name;//full name
    String schoolName;//School name
    String subject;//subject

    @ToMany
    @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "teacherId",targetProperty = "studentId")
    List<Student> studentList;
  ......getter and setter ......
} 
```

Data addition:

```
# epilogue

*   Tiktok Kwai is now popular with short videos. NDK Module development is becoming more and more important. More and more enterprises need this talent, and more people learn this. Audio and video development is often difficult, and this difficult technology is NDK The technology inside.
*   Audio and video/HD big picture/artificial intelligence/live broadcast/Tiktok and so on, which are the most closely related to users, and the most relevant technologies in our life, have been looking for the ultimate technology landing platform. windows System, and now it is a mobile system, and in the mobile system Android The majority is the premise, so AndroidNDK Technology is already a necessary skill for us.
*   We should study well NDK,About C/C++,jni,Linux In addition, audio and video codec technology, streaming media protocol, ffmpeg These are the necessary skills for audio and video development, and
*   OpenCV/OpenGl/These are also the necessary knowledge of image processing. The following are the data I collected and some pictures I made in those years, because I felt that video would be a big trend in those years. So I made some preparations in advance. Now take it out and share it with you.

**[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://codechina.csdn.net/m0_60958482/android_p7)**

![](https://img-blog.csdnimg.cn/img_convert/06ba1a351e2ced61156d1decb07172ee.png)

JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "teacherId",targetProperty = "studentId")
    List<Student> studentList;
  ......getter and setter ......
} 
```

Data addition:

```
# epilogue

*   Tiktok Kwai is now popular with short videos. NDK Module development is becoming more and more important. More and more enterprises need this talent, and more people learn this. Audio and video development is often difficult, and this difficult technology is NDK The technology inside.
*   Audio and video/HD big picture/artificial intelligence/live broadcast/Tiktok and so on, which are the most closely related to users, and the most relevant technologies in our life, have been looking for the ultimate technology landing platform. windows System, and now it is a mobile system, and in the mobile system Android The majority is the premise, so AndroidNDK Technology is already a necessary skill for us.
*   We should study well NDK,About C/C++,jni,Linux In addition, audio and video codec technology, streaming media protocol, ffmpeg These are the necessary skills for audio and video development, and
*   OpenCV/OpenGl/These are also the necessary knowledge of image processing. The following are the data I collected and some pictures I made in those years, because I felt that video would be a big trend in those years. So I made some preparations in advance. Now take it out and share it with you.

**[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://codechina.csdn.net/m0_60958482/android_p7)**

[External chain picture transfer...(img-r2ESzlPM-1630384555913)]

![](https://img-blog.csdnimg.cn/img_convert/27a8c7f1d27e7c46e028c53c75d83d8d.png)

Topics: Android Database Design Pattern