I am using GreenDAO for a local Android project. I am creating the login and register of the users (they work fine) the problem happens after one user is created. Registering more than one user throws this exception:
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)
Although I have set the user id to @Id(autoIncrement = true)
it seems as if the new Users are getting the same id. Also the INSERT INTO
sql shows (?,?, ...)
for all property values in the console.
What am I doing wrong here?
This is my 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;
}
}
This is my 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("");
}
}
There are other entities as well, but I don't think they are related to the error. Tell me if you need more info.
I changed the id type of long
to Long
and regenerated the greenDAO code and it works now. Looks like auto increment doesn't work well with the type long
. (Although in the documents it says both types are supported)