android.database.sqlite.SQLiteConstraintException:使用greenDAO ORM的唯一约束失败

时间:2020-07-18 08:11:54

标签: android mysql orm greendao

我正在将GreenDAO用于本地Android项目。我正在创建用户的登录名和注册名(他们工作正常),创建一个用户后会发生问题。注册多个用户会引发此异常:

    E/SQLiteLog: (1555) abort at 21 in [INSERT INTO "USER" ("_id","EMAIL","FIRST_NAME","LAST_NAME","LAND","PASSWORD","IMAGE_REFERENCE","ABOUT","ROLE_ID") VALUES (?,?,?,?,?,?,?,?,?)]: UNIQUE constraint failed: USER._id
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.databaseproject, PID: 7436
    android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: USER._id (code 1555)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at org.greenrobot.greendao.AbstractDao.insertInsideTx(AbstractDao.java:368)
        at org.greenrobot.greendao.AbstractDao.executeInsert(AbstractDao.java:351)
        at org.greenrobot.greendao.AbstractDao.insert(AbstractDao.java:319)
        at com.example.databaseproject.activity.MainActivity.register(MainActivity.java:107)
        at com.example.databaseproject.activity.MainActivity.access$500(MainActivity.java:23)
        at com.example.databaseproject.activity.MainActivity$1.onClick(MainActivity.java:69)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

尽管我已将用户ID设置为@Id(autoIncrement = true),但似乎新用户正在获得相同的ID。 INSERT INTO sql还在控制台中显示所有属性值的(?,?, ...)。 我在这里做错了什么? 这是我的User.java

package com.example.databaseproject.entity;

import androidx.annotation.Nullable;

import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.JoinEntity;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.ToMany;
import org.greenrobot.greendao.annotation.Unique;

import java.util.List;

@Entity
public class User {

    @Id(autoincrement = true)
    private long id;

    @NotNull
    @Unique
    private String email;
    @Nullable
    private String first_name;
    @Nullable
    private String last_name;
    @Nullable
    private String land;
    @NotNull
    private String password;
    @Nullable
    private String image_reference;
    @Nullable
    private String about;
    @NotNull
    private long role_id;

    @ToMany
    @JoinEntity(
            entity = UserMusicLiked.class,
            sourceProperty = "user_id",
            targetProperty = "music_id"
    )
    private List<Music> musicsLikedByThisUser;

    @ToMany
    @JoinEntity(
            entity = UserPlaylistFollow.class,
            sourceProperty = "user_id",
            targetProperty = "playlist_id"
    )
    private List<Playlist> playlistsFollowedByThisUser;

    /**
     * Used to resolve relations
     */
    @Generated(hash = 2040040024)
    private transient DaoSession daoSession;

    /**
     * Used for active entity operations.
     */
    @Generated(hash = 1507654846)
    private transient UserDao myDao;

    @Generated(hash = 1603819663)
    public User(long id, @NotNull String email, String first_name, String last_name, String land,
                @NotNull String password, String image_reference, String about, long role_id) {
        this.id = id;
        this.email = email;
        this.first_name = first_name;
        this.last_name = last_name;
        this.land = land;
        this.password = password;
        this.image_reference = image_reference;
        this.about = about;
        this.role_id = role_id;
    }

    @Generated(hash = 586692638)
    public User() {
    }

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getFirst_name() {
        return this.first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getLast_name() {
        return this.last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public String getLand() {
        return this.land;
    }

    public void setLand(String land) {
        this.land = land;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getImage_reference() {
        return this.image_reference;
    }

    public void setImage_reference(String image_reference) {
        this.image_reference = image_reference;
    }

    public String getAbout() {
        return this.about;
    }

    public void setAbout(String about) {
        this.about = about;
    }

    public long getRole_id() {
        return this.role_id;
    }

    public void setRole_id(long role_id) {
        this.role_id = role_id;
    }

    /**
     * To-many relationship, resolved on first access (and after reset).
     * Changes to to-many relations are not persisted, make changes to the target entity.
     */
    @Generated(hash = 1624161576)
    public List<Music> getMusicsLikedByThisUser() {
        if (musicsLikedByThisUser == null) {
            final DaoSession daoSession = this.daoSession;
            if (daoSession == null) {
                throw new DaoException("Entity is detached from DAO context");
            }
            MusicDao targetDao = daoSession.getMusicDao();
            List<Music> musicsLikedByThisUserNew = targetDao._queryUser_MusicsLikedByThisUser(id);
            synchronized (this) {
                if (musicsLikedByThisUser == null) {
                    musicsLikedByThisUser = musicsLikedByThisUserNew;
                }
            }
        }
        return musicsLikedByThisUser;
    }

    /**
     * Resets a to-many relationship, making the next get call to query for a fresh result.
     */
    @Generated(hash = 1901439151)
    public synchronized void resetMusicsLikedByThisUser() {
        musicsLikedByThisUser = null;
    }

    /**
     * To-many relationship, resolved on first access (and after reset).
     * Changes to to-many relations are not persisted, make changes to the target entity.
     */
    @Generated(hash = 952184019)
    public List<Playlist> getPlaylistsFollowedByThisUser() {
        if (playlistsFollowedByThisUser == null) {
            final DaoSession daoSession = this.daoSession;
            if (daoSession == null) {
                throw new DaoException("Entity is detached from DAO context");
            }
            PlaylistDao targetDao = daoSession.getPlaylistDao();
            List<Playlist> playlistsFollowedByThisUserNew = targetDao
                    ._queryUser_PlaylistsFollowedByThisUser(id);
            synchronized (this) {
                if (playlistsFollowedByThisUser == null) {
                    playlistsFollowedByThisUser = playlistsFollowedByThisUserNew;
                }
            }
        }
        return playlistsFollowedByThisUser;
    }

    /**
     * Resets a to-many relationship, making the next get call to query for a fresh result.
     */
    @Generated(hash = 1490831360)
    public synchronized void resetPlaylistsFollowedByThisUser() {
        playlistsFollowedByThisUser = null;
    }

    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 128553479)
    public void delete() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.delete(this);
    }

    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 1942392019)
    public void refresh() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.refresh(this);
    }

    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 713229351)
    public void update() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.update(this);
    }

    /** called by internal mechanisms, do not call yourself. */
    @Generated(hash = 2059241980)
    public void __setDaoSession(DaoSession daoSession) {
        this.daoSession = daoSession;
        myDao = daoSession != null ? daoSession.getUserDao() : null;
    }
}

这是我的MainActivity.java

package com.example.databaseproject.activity;

import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.databaseproject.CurrentUser;
import com.example.databaseproject.R;
import com.example.databaseproject.entity.DaoMaster;
import com.example.databaseproject.entity.DaoSession;
import com.example.databaseproject.entity.User;
import com.example.databaseproject.entity.UserDao;

import java.util.List;

public class MainActivity extends AppCompatActivity {


    private boolean isLogin = true;

    private EditText emailEditText;
    private EditText passwordEditText;
    private EditText firstNameEditText;
    private EditText lastNameEditText;
    private EditText landNameEditText;
    private Spinner roleSpinner;

    private TextView changeLoginRegisterText;
    private Button submitButton;

    private DaoSession daoSession;
    private UserDao userDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


// do this once, for example in your Application class
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "myDatabase", null);
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
        userDao = daoSession.getUserDao();
// do this in your activities/fragments to get hold of a DAO
//        MusicDao musicEntity = daoSession.getMusicDao();

        emailEditText = findViewById(R.id.edit_text_username);
        passwordEditText = findViewById(R.id.edit_text_password);
        submitButton = findViewById(R.id.button_submit);
        changeLoginRegisterText = findViewById(R.id.text_view_register);

        submitButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (isLogin) {
                    if (isFieldsValid())
                        login(emailEditText.getText().toString(), passwordEditText.getText().toString());
                } else {
                    if (isFieldsValid())
                        register(emailEditText.getText().toString(), passwordEditText.getText().toString());
                }
            }
        });

        changeLoginRegisterText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isLogin = !isLogin;
                updateUI();
            }
        });
    }

    private void updateUI() {
        if (isLogin) {
            changeLoginRegisterText.setText("Not a user? Create a new Account");
            submitButton.setText("Login");
        } else {
            changeLoginRegisterText.setText("Already a User? Login");
            submitButton.setText("Register");
        }
    }

    private void register(String email, String password) {

        //Check if user exists

        List<User> user = userDao.queryBuilder().where(UserDao.Properties.Email.eq(email))
                .limit(1)
                .list();
        if (user != null && user.size() > 0) {
            print(user.get(0).getEmail() + " Already Registered");
        } else {
            User newUser = new User();
            newUser.setEmail(email);
            newUser.setPassword(password);
            newUser.setRole_id(0);
            userDao.insert(newUser);
            print(newUser.getEmail() + " Registered successfully");

            setCurrentUser(newUser);
        }
    }

    private void login(String email, String password) {
//        UserDao userDao = daoSession.getUserDao();
        List<User> user = userDao.queryBuilder().where(UserDao.Properties.Email.eq(email))
                .where(UserDao.Properties.Password.eq(password))
                .limit(1)
                .list();
        if (user != null && user.size() > 0) {
            print(user.get(0).getEmail() + " Logged in");
            setCurrentUser(user.get(0));
        } else {
            print("Invalid Username or Password");
        }
    }

    private void setCurrentUser(User user) {
        CurrentUser.user = user;

    }

    private void print(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

    private boolean isFieldsValid() {
        return emailEditText != null && !emailEditText.getText().toString().equals("")
                && passwordEditText != null && !passwordEditText.getText().toString().equals("");
    }
}

还有其他实体,但我认为它们与错误无关。告诉我是否需要更多信息。

1 个答案:

答案 0 :(得分:0)

我将long的id类型更改为Long,并重新生成了greenDAO代码,现在可以使用了。看来自动递增不适用于类型long。 (尽管在documents中说两种类型都受支持)