Tomas Almeida Tomas Almeida - 2 months ago 11
Java Question

MongoDB Morphia only saving 1 user

Hi guys i'me having troubles using morphia for mongodb this is what im creating.
Im creating a spigot plugin for my hub server and im using mongodb with morphia for store my user object to my collection and this object only store 1 user instead of saving all users into the collection.

My user object

@Entity(value = "clientdata", noClassnameStored = true)
public class ClientData {

@Id
public int id;

@Indexed(options = @IndexOptions(unique = true))
private String uuid;

@Indexed
private String lastName, username, lastLoginDate, ip;

@Indexed
private int level, exp, joins, coins, pearls;

@Property("hats")
private List<Integer> hatsOwned;

public ClientData(){
this.hatsOwned = new ArrayList<>();

if(this.hatsOwned.isEmpty()){
this.hatsOwned.add(0);
}
}

public int getId() {
return id;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

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

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public int getLevel() {
return level;
}

public void setLevel(int level) {
this.level = level;
}

public int getExp() {
return exp;
}

public void setExp(int exp) {
this.exp = exp;
}

public int getJoins() {
return joins;
}

public void setJoins(int joins) {
this.joins = joins;
}

public void addJoins(int joins) {
this.joins += joins;
}

public int getCoins() {
return coins;
}

public void setCoins(int coins) {
this.coins = coins;
}

public int getPearls() {
return pearls;
}

public void setPearls(int pearls) {
this.pearls = pearls;
}

public List<Integer> getHatsOwned() {
return hatsOwned;
}

public void setHatsOwned(List<Integer> hatsOwned) {
this.hatsOwned = hatsOwned;
}

public void addNewHatOwned(int hatID){
this.hatsOwned.add(hatID);
}

public String getLastLoginDate() {
return lastLoginDate;
}

public void setLastLoginDate(String lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
}


My mongo manager class

public class MongoManager {
private static MongoManager ins = new MongoManager();

private MongoClient mc;
private Morphia morphia;
private Datastore datastore;
private ClientDAO userDAO;

public static MongoManager get() {
return ins;
}

public void init() {
ServerAddress addr = new ServerAddress("127.0.0.1", 27017);
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(MongoCredential.createCredential("union", "admin", "union16".toCharArray()));
mc = new MongoClient(addr, credentials);

morphia = new Morphia();

morphia.map(ClientData.class);

datastore = morphia.createDatastore(mc, "admin");
datastore.ensureIndexes();

userDAO = new ClientDAO(ClientData.class, datastore);
}

public void disconnect(){
this.mc.close();
}

public ClientData getUserByPlayer(Player player) {
ClientData du = userDAO.findOne("uuid", player.getUniqueId().toString());
long time = System.currentTimeMillis();

if (du == null) {
du = new ClientData();
du.setUuid(player.getUniqueId().toString());
du.setCoins(0);
du.setExp(0);
du.setJoins(0);
du.setLastLoginDate(DateFormat.getTimeInstance().format(time));
du.setLevel(0);
du.setPearls(0);
du.setIp(player.getAddress().getAddress().toString());
du.setUsername(player.getDisplayName());
du.setLastName(player.getName());
du.setHatsOwned(null);
userDAO.save(du);
}
return du;
}


public void saveUser(ClientData user) {
userDAO.save(user);
}

public List<ClientData> getAllUsers() {
return userDAO.find().asList();
}
}

Answer

You can't insert more than one because you have duplicateKey: you can't use an @id with primitive type without setting a unique value yourself.

You defined your id like this:

@Id
public int id;

Even though you never set any value for id, primitive types are initialized to 0, so you end up trying to insert multiple documents with the same key.

Solution:

You can either :

  • change your id to String: @Id String id;
  • change your id to ObjectId: @Id ObjectId id;
  • keep @Id int id and manually set a unique value to it (player.getUniqueId() for instance).

The first 2 options will work because they won't be initialized and will be null. Mongo will then generate a unique id for you.