This column focuses on sharing the knowledge of large-scale Bat interview, and it will be updated continuously in the future. If you like it, please click a follow
Interviewer: Have you ever encapsulated SqliteDatabase? Did you design your own database framework? Or just stick with frameworks like Ormlite and greenDao
Psychological analysis: The interviewer is more in the framework of knowledge, especially database, most developers do not understand why can be directly used, Tencent instead requires you to write. In fact, small companies are mostly used. Big companies, on the other hand, have more requirements and changes to consider. So when asked if they’ve ever done a data framework, a lot of people just say I’ve used it. That’s not a reason to admit you
Job Seeker: You should start by explaining why sqliteDatabase’s API is rigid, undoable, and prone to errors. From the perspective of overall database architecture design, tell the interviewer step by step how you implemented the database framework
The database is very important in some specific requirements, such as persistent data, some data that does not need to be real-time or unchanged for a long time, can be stored in the database for caching, so that even if the user has a bad network or disconnection, it can still view some of the previous data. Like news or consulting. This is inevitable. Improve the user experience.
Google provides us developers with basic database manipulation classes, as well as SqliteDatabase to create and modify databases and tables directly
But this is not enough to meet our usual agile development as an application layer programmer, most of the time just want to care about storing and reading data, data processing and other problems to solve.
Instead of spending time and energy on how to store, how to access the database data. This is the premise of architecture. Encapsulate some process-oriented algorithm or business logic that can be called again. Easy to expand, high sensitivity. Let the programmer focus on sorting out project requirements and logic. Free the brain, improve work efficiency.
Now there are many tripartite frameworks in database, such as GreenDao,Afinal, xUtils, ThinkAndroid, Volley and so on.
But after these three – party imports, the number of files is too large. And many of them integrate web loading frameworks, image loading frameworks.
So there’s some coupling. For example, I only like xUtils database framework, not its network loading, want to use Volley network loading framework.
Do how? Import both, right? Yes, you can, but the number of files on the project is too large. Compile-time stress. And some companies want programmers to write their own frameworks instead of using frameworks published by others, so the code is highly extensible. What problems can be timely modified. If the imported tripartite library has problems during the project maturity phase. Is it necessary to override the library, import another one, write the logic again, and who can guarantee that the library imported again will not make mistakes?
I show the general packaging ideas in the form of pictures.
Corresponding UML diagram
It’s also very easy to use, as the mapping logic here and the underlying source code for GreenDao use the same principle. Table and class attribute mappings are used and cached. Links are re-established only when the table links are switched.
Advantages:
1, support SQL statements from the splicing. The database executes SQL statements directly.
2, support the incoming class object to add, delete, change, check, such as User, in insert time, insert User instance, attributes are encapsulated in the User. Get its attribute values by reflection and store them in the database.
3, high expansion, each new storage type. Just inherit DefaultBaseDao. You can do something unique to this class here.
4, support multi-database switch, multi-database operation. At the same time, support database management, multi-database multi-version multi-user upgrade, adopt XML script upgrade. The script statement here is not wrapped.
5, support Boolean, byte, short, int, long, float, double data types of storage and reading.
Precautions for use:
1. When creating a storage data class, use annotations to annotate the class name (table name @dbTable) and class attributes (table field @dbField). If there is a primary key (@dbPrimaryfield), this is also required.
2. Create a link between the corresponding Dao layer class and the database.
When using the import gandle: compile ‘com. Singleshu8: LemonDao: 1.0.4’
Create a Dao layer where you can manipulate the database, such as when multiple data upgrades are performed. External extension
public class FileDao extends DefaultBaseDao {
}
Copy the code
@DbTable(value = "tb_file")
public class FileModel {
@DbPrimaryField(value = "id")
private int id;
@DbField(value = "tb_filename")
private String fileName;
@DbField(value = "tb_filepath")
private String filePath;
@DbField(value = "tb_fileid")
private int fileId;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public int getFileId() {
return fileId;
}
public void setFileId(int fileId) { this.fileId = fileId; }}Copy the code
@DbTable(value = "tb_user")
public class User {
@DbPrimaryField(value = "id")
private Integer id;
@DbField(value = "user_name")
private String name;
@DbField(value = "user_address")
private String address;
@DbField(value = "user_psw")
private String psw;
@DbField(value = "user_status")
private Integer status;
@DbField(value = "user_id")
private String user_id;
@DbField(value = "isMe")
private Boolean isMe;
@DbField(value = "myAge")
private Double myAge;
@DbField(value = "myPhone")
private Long myPhone;
@DbField(value = "aShort")
private Short aShort;
public User(String name, String address, String psw, Integer status, String user_id, Boolean isMe, Double myAge, Long myPhone, Short aShort) {
this.name = name;
this.address = address;
this.psw = psw;
this.status = status;
this.user_id = user_id;
this.isMe = isMe;
this.myAge = myAge;
this.myPhone = myPhone;
this.aShort = aShort;
}
public User() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public Boolean getMe() {
return isMe;
}
public void setMe(Boolean me) {
isMe = me;
}
public Double getMyAge() {
return myAge;
}
public void setMyAge(Double myAge) {
this.myAge = myAge;
}
public Long getMyPhone() {
return myPhone;
}
public void setMyPhone(Long myPhone) {
this.myPhone = myPhone;
}
public Short getaShort() {
return aShort;
}
public void setaShort(Short aShort) {
this.aShort = aShort;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' + ", address='" + address + '\'' + ", psw='" + psw + '\' ' +
", status=" + status +
", user_id='" + user_id + '\'' + ", isMe=" + isMe + ", myAge=" + myAge + ", myPhone=" + myPhone + ", aShort=" + aShort + '}'; }}Copy the code
public class UserDao extends DefaultBaseDao<User> {
// @Override
// public Long insert(User entity) {
// List<User> list=query(new User());
// User where = null;
// for (User user:list)
// {
// where =new User();
// where.setUser_id(user.getUser_id());
// user.setStatus(0);
// Log.i(TAG,"User"+user.getName()+"Change to unlogged state");
// update(user,where);
// }
// Log.i(TAG,"User"+entity.getName()+"Login");
// entity.setStatus(1);
// returnsuper.insert(entity); } /** * get the current login User * @return
*/
public User getCurrentUser() {
User user=new User();
user.setStatus(1);
List<User> list=query(user);
if(list.size()>0)
{
return list.get(0);
}
returnnull; }}Copy the code
The specific use
public class MainActivity extends AppCompatActivity {
private IBaseDao iBaseDao;
String dbFile;
int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); / / database address folder dbFile = Environment. External.getexternalstoragedirectory () getAbsolutePath () +"/myDb"; . / / 6.0 + dynamic application permissions PermissionUtils getInstance (). The requestPermission (this); } public void click(View View){switch (view.getid ()){//myselft.db add user to databasecaseDa dd_user R.i: / / to establish the link of database and table iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (UserDao. Class, the User. The class, dbFile,"myselft.db");
//iBaseDao.insert("insert into tb_user(user_name,user_address,user_psw,user_status,user_id,isMe,myAge,myPhone,aShort) Values (' ghost dao ', 'the land of the hexapole', '123456', 1, 'user_90', 'true', 1.234, 457864745123 (4)"); Short si = 123; Short si = 123; User user = new User("Ghost dao"."Land of the Six Poles."."123456", 0,"user_"+i,true, 1.234, 457864745 l, si); iBaseDao.insert(user); i++;break;
caseR.id.add_file: / / when the need to switch table storage, you need to build links iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (dbFile FileDao. Class, FileModel. Class,"myselft.db");
FileModel fileModel = new FileModel();
fileModel.setFilePath("d/as:/");
fileModel.setFileName("qq.apk");
fileModel.setFileId(123);
iBaseDao.insert(fileModel);
break;
caseR.id.add_sqlite_file: / / when the need to switch table storage, you need to build links iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (dbFile FileDao. Class, FileModel. Class,"mydownfile.db");
FileModel fileModel1 = new FileModel();
fileModel1.setFilePath("d/as:/");
fileModel1.setFileName("qq.apk");
fileModel1.setFileId(123);
iBaseDao.insert(fileModel1);
break; // Delete the usercaseR.id.delete_user: / / to establish the link of database and table iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (UserDao. Class, the User. The class, dbFile,"myselft.db"); //User user2 = new User(); //user2.setUser_id("user_0"); // Because the mobile database cannot store Boolean values, Boolean values must be assigned when looking for conditions. Otherwise the default isfalse! //user2.setMe(true); //iBaseDao.delete(user2); Ibasedao.delete (ibasedao.delete (ibasedao.delete))"delete from tb_user where user_id = 'user_0'"); Ibasedao.delete ("delete from tb_user where user_id = ?",new String[]{"user_0"});
break; // Query the usercaseR.id.query_user: / / to establish the link of database and table iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (UserDao. Class, the User. The class, dbFile,"myselft.db");
User user1 = new User();
user1.setName("Ghost dao"); // Because the mobile database cannot store Boolean values, Boolean values must be assigned when looking for conditions. Otherwise the default isfalse! // user1.setMe(true); List<User> users = ibasedao.query (user1); //List<User> users = ibasedao.query (user1,"user_id", 0, 10); //List<User>users = ibasedao.query ("Select * from tb_user where user_name = 'user_name '",User.class); // List<User>users = ibasedao.query ("select * from tb_user where user_name = ?",User.class,new String[]{"Ghost dao"});
for (User user3:users) {
Log.i("tag00",user3.toString());
Log.i("tag00"."= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
}
break; // Update the usercaseR.id.update_user: // Create a link between the database and the table. So you don't have to build new links iBaseDao = BaseDaoFactory. GetInstance () getSqliteComponent (UserDao. Class, the User. The class, dbFile,"myselft.db"); NewUser = newUser (); newUser = newUser (); newUser.setName("Sword of the South.");
User where = new User();
where.setMe(true);
where.setUser_id("user_1");
iBaseDao.update(newUser,where); Ibasedao.update (ibasedao.update (ibasedao.update (ibasedao.update (ibasedao.update))"Update tb_user set user_name = 'Blood Angel - Austin' where user_name = 'Sword of Heaven '"); Ibasedao.update (ibasedao.update (ibasedao.update (ibasedao.update))Update tb_user user_name = 'Blood Angel - Austin '");
break;
}
}
@Override
protected void onDestroy() { super.onDestroy(); Ibasedao.close (); ibasedao.close (); }}Copy the code
There are things about database branch libraries and multi-version multi-user script upgrades, which are rarely used in small projects. Small projects are usually done in a few tables. Query is to add a userId, but this can be uncomfortable when there is too much data. A database update can concatenate strings directly when tables are small. But when there are too many tables, this is definitely not correct.
If the database branch library and multi-version multi-user upgrade interested friends. You can contact me and click about me. I really hope to communicate with you and make progress together