In the past several articles, we have mastered the functions of LitePal’s table management module, and we believe that you have experienced the convenience of creating tables, upgrading tables, and establishing table associations with LitePal.

So starting with this article, we’ll be on a journey to a new module that uses LitePal for CRUD operations on tables. For those of you who haven’t read the previous article, it’s best to refer to Android Database master Tip # 4 — Use LitePal to establish table associations.

LitePal provides a wide range of APIS for CRUD operations. One article would not cover all of them, so this one will focus on the storage API.

LitePal’s project address is: github.com/LitePalFram…

Traditional ways to store data

The most traditional way to store data is by concatenating strings of SQL statements, but this is a bit too “traditional” and we won’t discuss it here. In fact, Android specifically provides an easy way to store data without having to write AN SQL statement. Let’s look at the insert() method in SQLiteDatabase:

public long insert(String table, String nullColumnHack, ContentValues values)

Copy the code

As you can see, the insert method takes three arguments. The first argument is the table name. The second argument is usually not used, and null is passed. So, for example, if we want to insert a news item into the news table, we can write:

SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); Values. Put ("title", "this is a news headline "); Values. Put ("content", "This is a news item "); values.put("publishdate", System.currentTimeMillis()); long id = db.insert("news", null, values);Copy the code

The put() method of ContentValues is called to add the data to store. The put() method takes two arguments. The first argument is the name of the corresponding column in the database table, and the second argument is the value to store. The news is inserted into the news table, and the id of the row is returned as the return value.

Easy to use, right? Indeed, the insert() method provided in SQLiteDatabase is much simpler than using SQL statements directly. However, the insert() method is not perfect, and it has many disadvantages. For example, it does not consider table association, and we need to manually store the foreign keys of the associated table. For example, there is no provision for bulk storage. When we have a collection of data that needs to be stored, we need to loop through the collection and then call insert() again and again to insert the data.

Ok, so that’s a brief introduction to the traditional use of stored data, because there really isn’t much more to it, and it’s not our main story today. Next, let’s take a look at today’s surprise and learn how to use LitePal for database storage.

Use LitePal to store data

LitePal’s storage-related apis are few and far between, but there are plenty of ways to use it, and it’s surprisingly easy to use LitePal to store data compared to the traditional INSERT () method. So today we’re going to take a look at all the ways to use LitePal to store data.

In previous articles, we have built the News, Comment, Introduction, and Category entity classes in the project, which enable LitePal to automatically create the corresponding tables. Now looking at these entity classes, we see that none of them have inheritance structures. Yes, because LitePal does not need any inheritance structure for these entity classes to perform table management operations, it was not written for simplicity at the time. For CRUD operations, LitePal requires that all entity classes inherit from DataSupport, so we need to add the inheritance structure here. Modify the code for the News class to look like this:

public class News extends DataSupport{
Copy the code

As you can see, you’re just inheriting the News class from DataSupport, nothing else has changed. The same changes are used for the other Comment, Introduction, and Category classes, which will not be demonstrated here.

After inheriting DataSupport, these entity classes have CRUD capability. For example, if you want to store a piece of data in a news table, you can write:

News.settitle (" This is a news title "); News.setcontent (" This is a piece of news content "); news.setPublishDate(new Date());Copy the code

How’s that? You don’t need SQLiteDatabase, you don’t need ContentValues, you don’t need to assemble data by column names, you don’t even need to specify table names, you just need to new out a News object, and then pass in the data that you want to store through the setter method, Finally, you need to call the save() method, which is inherited from the DataSupport class.

In addition, the save() method still has a return value. We can determine whether the storage was successful based on the return value. For example, write:

Toast.maketext (context, "store successfully ", toast.length_short).show(); Toast.maketext (context, "failed to store ", toast.length_short).show();Copy the code

As you can see, the save() method returns a Boolean value indicating whether the storage succeeded or failed, but it also indicates that the method does not throw an exception. Some friends want to throw an exception if the storage fails, instead of returning false, so use the saveThrows() method instead, as shown below:

News.settitle (" This is a news title "); News.setcontent (" This is a piece of news content "); news.setPublishDate(new Date());Copy the code

We use the saveThrows() method to store data. If the storage fails, a DataSupportException is thrown. We can handle the storage failure by catching this exception.

Those of you who are careful may have noticed that the insert() method used to store data returns the id of the row that was inserted. But the save() method in LitePal returns a Boolean value, so how do we get the id that corresponds to the data stored successfully? LitePal uses a very clever approach to this, remember we defined an ID field in each entity class? When the save() or saveThrows() method is successfully called, LitePal automatically assigns the id corresponding to the data to the id field of the entity class. Let’s do an experiment. The code looks like this:

News.settitle (" This is a news title "); News.setcontent (" This is a piece of news content "); news.setPublishDate(new Date()); Log.d("TAG", "news id is " + news.getId()); Log.d("TAG", "news id is " + news.getId());Copy the code

Print the news ID before save, and print it again after save. Now run it, and the print result is as follows:

OK, the id printed before save is 0, indicating that the id field has not been assigned, and the ID printed after save is 1, indicating that the ID field has been assigned. Then let’s check whether this record has been successfully stored in the database table again, as shown in the figure below:

As you can see, the news has indeed been stored, and the corresponding ID is 1, which is the same as what we printed earlier.

In fact, LitePal helps us do a lot of things when we store data. For example, if there is an association between multiple entity classes, we don’t need to think about how to establish the association between data when we store data. Because LitePal does everything for us.

The relationship between Comment and News is many-to-one. A piece of News can contain multiple comments, so we can write it like this:

Comment comment1 = new Comment(); Comment1. setContent(" Comment! ); comment1.setPublishDate(new Date()); Comment comment2 = new Comment(); Comment2. setContent(" like one "); comment2.setPublishDate(new Date()); news.getCommentList().add(comment1); news.getCommentList().add(comment2); News.settitle (" the second news title "); News.setcontent (" Second news content "); news.setPublishDate(new Date()); news.setCommentCount(news.getCommentList().size());Copy the code

As you can see, first we store a Comment1, then we store a Comment2, and then we add those two Comment objects to the News’s commentList before we store the News, In this way, it means that the two comments belong to the News object. Finally, the News is stored in the database, so that the association between them will be established automatically. Let’s look at the database table to check. First, look at the news table, which looks like this:

OK, the second news item has been successfully stored in the news table. The news item id is 2. So where do we see the correlation? As we learned in the previous article, in many-to-one relationships, the foreign key is stored in multiple parties, so we need to look at the association in the comment table, as follows:

As you can see, both comments have been successfully stored in the comment table, and both comments have a news_id of 2, indicating that they belong to the second story. How about setting up the relationship between the entity classes before storing the data, then calling the save() method, and the relationship between the data will be automatically established? The above code is only one way to use the many-to-one case, and one to one and many to many cases, in fact, the use of the same, I believe you have been able to deduce the three.

In addition, LitePal also provides a method for storing collection data. For example, if we have a collection of News, how should we store each News in this collection? The traditional way to write it is:

for (News news : newsList) {
Copy the code

A loop loops through each News object in the collection, calling the save() method one by one. Of course, this method can be written, but it is inefficient, because when calling the save() method, it will not only perform the storage operation, but also analyze the association relationship of the News class, so it is obviously time-consuming to reanalyze the association relationship every time in the loop. Therefore, LitePal provides a saveAll() method for storing collection data, as follows:

DataSupport.saveAll(newsList);
Copy the code

The saveAll() method accepts a Collection parameter by passing in the Collection data to be stored. This method would do exactly the same thing as the above code, but it would be much more efficient and much simpler to write.

Ok, now that we’ve covered all of the storage operations provided by LitePal, that’s it for today. The next article will cover update and delete operations. If you are interested, please read on