Bedding before going into the pit

Yesterday in the previous [GreenDao project access] www.jianshu.com/p/dac3bd9ba… “Explained a process of using GreenDao in the project. Due to the lack of time, I did not explain in detail some problems related to adding, deleting, modifying and checking. Today, I will give you a supplement.

public class User extends BaseBean
{
    private int memberSex;/ / gender
    private String memberLastX;/ / X COINS
    private String memberNickname;/ / nickname
    private String memberIcon;// Avatar address link
    private String memberMobile;/ / cell phone number
    private int memberId;/ / user ID
    private String memberDetailAddr;// The user's detailed address
    private String memberLastExperience;// User experience
    private String memberLevelName;// User level nickname
    private long memberBirthday;// The user's birthday
    private String memberProvince;// User location
}Copy the code

The above is the entity class I used to obtain interface user information in my actual development, and then I annotated the entity class according to the steps as follows:

@Entity
public class User extends BaseBean
{
    @Id
    private Long id;
    private int memberSex;/ / gender
    private String memberLastX;/ / X COINS
    private String memberNickname;/ / nickname
    private String memberIcon;// Avatar address link
    private String memberMobile;/ / cell phone number
    private int memberId;/ / user ID
    private String memberDetailAddr;// The user's detailed address
    private String memberLastExperience;// User experience
    private String memberLevelName;// User level nickname
    private long memberBirthday;// The user's birthday
    private String memberProvince;// User location
}Copy the code

I don’t know if you have noticed carefully, but I defined a field of type Long in the entity class as ID (developed according to the official Demo). It was this ID that caused me to fail once. I would like to give you a detailed description of the problem I encountered at that time and the solution:

I Make project to generate the corresponding UserDao, DaoMaster and DaoSession according to the above entity class. This is what I do when I cache User information in my code. I first fetch the User data from the server, and then convert it to a User object for local caching using GreenDao, as follows:

/** * Cache user information ** @paramuser
     */ public void cacheUserInfo(User user)
    {
        UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao();
        userDao.save(user);
    }Copy the code

GreenDao provides three methods for storing data:

  • save(T entity) “Saves” an entity to the database: depending on the existence of the key property, it will be inserted (key is null) or updated (key is not null). Check whether the key property exists, update the data if it exists, and insert the data if the key is null. What’s the key here? So that’s where I got screwed today, because this key is my new Long ID field, which is the primary key in the table
  • insert(T entity) Insert an entity into the table associated with a concrete DAO. Insert entity class, this is direct insert.
  • insertOrReplace(T entity) Insert an entity into the table associated with a concrete DAO. Inserting entities into tables associated with specific DAOs is explained by the official API, but its actual effect is very similar to svAE, in that it is modified if it exists and no inserts exist.

Here first say about the query method, the official query method is:

  • loadByRowId(long rowId)
  • load(K key) Loads the entity for the given PK. Get objects by primary key, that is, by ID

But I only memberId entity class, which is generated on the server Id, so definitely can’t use these two methods to obtain data, and then check the document and found [criteriabuilder < T >] greenrobot.org/files/green… Several methods are provided in QueryBuilder:

  • unique() Shorthand for build() . Shorthand for build() .unique() ; see Query.unique() for details. To execute a query more than once, you should build the query and keep the Query object for efficiency reasons. Build a Query

    object that can be used to retrieve data over and over again

Into the pit ing

How did I get into the hole? At that time, I saw the document and found that save was very smart, so I thought to use save, which is to make a judgment before inserting, save time and effort, and then I have the above code, and then I get the cached data in the personal center, the method is as follows:

 /** * Get the user object ** from the local cache@paramMemberId User ID *@returnReturn user information */
    public User getUserInfoFromCache(String memberId)
    {
        UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao();
        Query<User> query = userDao.queryBuilder().where(UserDao.Properties.MemberId.eq(memberId))
                                   .orderDesc(UserDao.Properties.MemberId).build();
        return query.unique(a);
    }Copy the code

It seems that there is no problem, and then I went to run the program test, the first time found that Shouting, as expected, after the execution of the database really had a line of data, fart exit again, unexpectedly collapsed, a look at the log prompt: Expected unique result, but count was 2 The method above is my query conditions. The where (UserDao. Properties. MemberId. Eq (MemberId)), namely MemberId is equal to the current user, print as expected database has two data, then find the reason, affirmation is to find in the cache method, Found save also no problem ah, think impassability of time must kill is to see the source code

Out of the pit

The source code for Save is as follows:

  public void save(T entity) {
        if (hasKey(entity)) {
            update(entity);
        } else{ insert(entity); }}Copy the code

Update/insert (); hasKey (); hasKey ();

abstract protected boolean hasKey(T entity);Copy the code

It is an abstract method, so I can only find it in its descendant class UserDao

@Override
public boolean hasKey(User entity)
 {   
     returnentity.getId() ! =null;
 }Copy the code

Finally found the kidnapper, that’s right, is the Long id we define this field, it turned out that he is whether the existence before insert, if there is no insert, if there is update, then I see, I when inserting data access to data from the server, only memberId, without a local database id, So the second cache is still performing the insert operation, and then there must be a problem in the query, the truth can be solved. Here’s my solution:

/** * Cache user information ** @paramuser
     */ public void cacheUserInfo(User user)
    {
        User oldUser = getUserInfoFromCache(user.getMemberId() + ""); if (oldUser ! = null) { user.setId(oldUser.getId()); } UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao(); userDao.save(user); }Copy the code

If there is a memberId that is the same as that of GreenDao, insert it into user. If there is a GreenDao id, insert it into user. Ok, problem solved. Add @id to memberId instead of adding Long ID to memberId. You can see the following modified code:

@Entity
public class User extends BaseBean
{
    private int memberSex;/ / gender
    private String memberLastX;/ / X COINS
    private String memberNickname;/ / nickname
    private String memberIcon;// Avatar address link
    private String memberMobile;/ / cell phone number
    @Id
    private int memberId;/ / user ID
    private String memberDetailAddr;// The user's detailed address
    private String memberLastExperience;// User experience
    private String memberLevelName;// User level nickname
    private long memberBirthday;// The user's birthday
    private String memberProvince;// User location
}Copy the code

Then Make project, execute, error, and check hasKey code:

 @Override
    public boolean hasKey(User entity) {
        throw new UnsupportedOperationException("Unsupported for entities with a non-null key");
    }Copy the code

So, don’t think about this idea. If you have a better way, please leave a comment below. thank you I will update a little knowledge to you every day. If you are interested, you can pay attention to it. I don’t know when I can help you.