What do Java game developers use for Database persistence?

I use straight JDBC. I then got on with my life and wrote some games :slight_smile:

Cas :slight_smile:

I should totally unleash my minimalistic JDBC wrapper upon you!

It takes the cruft out of the CRUD. :persecutioncomplex:

It barely takes any time at all to write something like that though with a few annotations here and there. I don’t have enough database stuff to warrant even bothering with it though.

Cas :slight_smile:

Sure, it’s not hard, but I haven’t seen any jdbc wrapper as convenient as mine, yet :slight_smile:

I’ll post it in a few days, when I removed the worst bits :slight_smile:

I would really like to see that wrapper, Riven. I’ve been pondering creating one myself, but I’ve been busy in school.

We just finished a JSP/EJB 3.0 project. I love EJB, though it is rather complex, and impossible to host cheaply. Please post this wrapper, so I won’t have to resort to put up a private EJB-server ^^

I currently only have tested bindings to a MySQL db. It should work on every database that supports simple INSERT,SELECT,UPDATE,DELETE queries, because that’s pretty much what this wrapper does.

The wrapper is really ‘hands off’ and non-intrusive, so the database table-design is leading. No effort is made into even storing metadata like @nullable. You’ll get a typical SQLException from the server instead if you try to write a null value where it’s not allowed.

A typical Account & Deposit class ‘backed’ by tables would look like:


public class Account extends DataObject {
   public String username;
   public String passhash;
   public String passsalt;
   public String emailaddress;
   public int money;

   public Account() { super(); }
   public Account(int id) { super(id); }
}

public class Deposit extends DataObject {
   public Account account;
   public int amount;

   public Deposit() { super(); }
   public Deposit(int id) { super(id); }
}

Usage:

Account account = new Account(3421); // performs a SELECT

Deposit deposit1 = new Deposit(); // no SELECT
deposit1.account = account;
deposit1.amount = 40;
deposit1.insert();
System.out.println("deposit #1 ID="+deposit1.id());

Deposit deposit2 = new Deposit(); // no SELECT
deposit2.account = account;
deposit2.amount = 42;
deposit2.insert(); // INSERT
System.out.println("deposit #2 ID="+deposit2.id());

deposit2.amount += 3;
deposit2.update(); // UPDATE

deposit1.delete(); // DELETE

Say you want to query all Deposits of an Account:


public class Account extends DataObject {
   public String username;
   public String passhash;
   public String passsalt;
   public String emailaddress;
   public int money;

   public Account() { super(); }
   public Account(int id) { super(id); }

   public List<Deposit> getDeposits() {
      // this is so common, that I will probably move the actual query behind a utility method.
      return QueryDataObject.selectAll(Deposit.class,
         "SELECT * FROM deposit WHERE account = ?",
         this /* varargs: every '?' in the query requires an additional argument */);
   }
}

Say you want to query the Account of a Deposit:


public class Deposit extends DataObject {
   public Account account;
   public int amount;

   public Deposit() { super(); }
   public Deposit(int id) { super(id); }

   public Account selectAccount() {
      return (this.account == null) ? null : this.account.select();
   }
}

This shows the following:


Deposit d = new Deposit(37); // SELECT * FROM deposit WHERE somePrimaryKey = 37
// d.account is an instance, but is NOT filled with data, just an identifier, hence:
d.account.select(); // SELECT * FROM account WHERE somePrimaryKey = d.account.id()

The DataObject class allows you to override the default names for the tablename and primarykey column.


public class DataObject {
   public int id;
   
   //
   
   public String getTableName() {
      return this.getClass().getSimpleName().toLowerCase(); // "Account" -> "account"
   }
   
   public String getPrimaryKey() {
      return this.getTableName() + "id"; // "Account" -> "accountid"
   }
}

public class Account extends DataObject {
   @Override
   public String getPrimaryKey() {
      return "accountnr";
   }
}

The names of the (other) fields/colums are not configurable. They are used as-is. Java enums are supported and map directly to MySQL’s ENUM type.

This is really all there is to it. Well, there is more, like connection pools and preInsert / preUpdate / postDelete / postSelect callbacks, so you can implement poor man’s java-side triggers.

It’s really simple, so you’re really doing queries select()s, update()s, delete()s on individual objects. For select()s we have the QueryDataObject class, with methods which return List<…>

Is this what you’re looking for? I’ll only make it public when somebody actually needs it.

Seems legit :smiley: I like it! Very simple and easy to use. You really should publish it. I know I’d love to poke around the code a bit, to see how it all fits together. It might be just what I need.

I wonder how well akka’s data-store works…that could potentially kill two birds with one stone for massive entity systems.

How’s free grab you? JavaEE 6 on OpenShift

Akka doesn’t have anything like a database or other flavor of data store that I’m aware of. Is there something specific you’re referring to?

I thought that it has a persistent data-store, but it’s highly likely I’m mistaken.

Akka has support for libraries like mongodb and redis, but only to use them as a durable backing for actor mailboxes, for when you need pending messages to survive restarts of the entire program. Other than that, it’s not concerned with storage at all.

That’s pretty cool. :smiley: Similar to my design except I don’t need POJOs to inherit anything special. Well I spent a bit of time on this and posted it up on sourceforge. I’ll post something in the Share Code section.

I’m late to this party, but a friend of mine is working on a neat project:
https://code.google.com/p/fado/
I takes SQL you hand write and it generates Java classes. You then use the Java classes in your code, so you have a nice, type safe API for your queries. It parses the SQL and knows about the database schema, so it can be smart. I haven’t seen this approach done before. Here’s a little example:
https://code.google.com/p/fado/source/browse/trunk/source/play/PlayAllergies2.java
I’ve prodded him to put some examples on the front page.

Going the other way, trying to emit SQL with a Java API, doesn’t seem to work too well. Hiding the SQL entirely is fine for simple cases but eventually you tend to need to go under the hood, and thar be dragons. Simple cases are easy to write the SQL for, and you write the best SQL for complex cases anyway. So write your SQL and use Fado to keep your Java source from getting nasty. That is the idea, I believe.

I think you’re right in that the ORM impendance mismatch is probably better bridged by generating classes from relations than the other way around. It’s a cool concept your friend is pursuing! But it also hinges on the tools available within the language, making queries and such easier. And the two-step cross-language compilation process is always going to feel like a hurdle.

Aye, he says he has half an Eclipse plugin built. :slight_smile:

I’ve used Hibernate+JPA in the past but I find JPA based ORM a bit too clunky for “simple” client app usage, plus you always need half a dozen libraries of varying sizes just to be able to do basic persistence stuff. Since Play 2 started to default to EBean in stead of Hibernate I investigated it and found it a surprisingly neat and concise API that is for a change decently documented, updated quite regularly and to put icing on the cake is available through a maven repository; I’ll certainly consider it for a future project.