Database - noobmobile/GroovyBukkitAPI GitHub Wiki

Databases

GroovyBukkitAPI uses norm. Just call useDatabase() on your enable() and you'll be ready to use it.

@Entity
@Inject
@Table(name = "groovyusers")
class User {

    @Id
    String name
    int blocks

}
  def onBreak = { BlockBreakEvent e ->
        def user = main.database().where("name=?", e.player.name).first(User)
        user.setBlocks(user.getBlocks() + 1)
        e.player.sendMessage("$user.blocks")
        main.database().upsert(user)
    }

Method Injections

GroovyBukkitAPI already injects to you the following methods into your domain objects:

  • MyObject.findByProperty() e.g.: User.findByName(name)
  • MyObject.findAllByProperty() e.g.: User.findAllByBlocks(blocks)
  • MyObject.findAll() e.g.: User.findAll()
  • MyObject.save() e.g.: user.save()
  • MyObject.delete() e.g.: user.delete()
  • MyObject.topXProperty() pseudo-regex: (top|order|orderBy)(number?)(asc|desc?)(by?)(property) (if Desc or Asc is specificied, default is Desc) e.g:
User.topKills() // order by kills desc, no limit
User.top10Kills() // order by kills, desc, limit 10
User.top50AscKills() // order by kills, asc, limit 50
User.order20AscByDeaths() // order by deaths, asc, limit 20
User.orderByAscDeaths() // order by deaths, asc, no limit
def onBreak = { BlockBreakEvent e ->
        def user = User.findByName(e.player.name) ?: new User(name: e.player.name)
        user.setBlocks(user.getBlocks() + 1)
        e.player.sendMessage("$user.blocks")
        user.save()
    }

Be careful to call all these methods in async.

Converters

GroovyBukkitAPI automatically provides to you the following converters:

  • ItemStack
  • Location
  • Map

So you don't need to use @Convert from javax. But if you want to use, no problems, nOrm will handle to you.

@Entity
@Inject
@Table(name = "groovyusers")
class User {

    @Id
    String name
    int blocks
    Map<String, Integer> kills
    Location lastSeen
    @Convert(converter = MyAttributeConverter.class)
    CustomThing customThing

}

Database config

It'll be generated a database.yml with the following configurations:

database:
  type: MYSQL // Avaliable: SQLITE, MYSQL
  host: localhost
  port: '3306'
  user: admin
  password: ''
  database: test

Cache

It's not recommended query/update database all time, specially on Bukkit, where we have 20 ticks per second (this can lead to thousands of database operations easily)

@ToString
@Entity
@Inject
@Table(name = "groovymachines")
class Machine {

    @CacheOptions(loadAllOnEnable = true, saveAllOnDisable = true)
    static final Cache<Location, Machine> CACHE = new Cache<>(Machine, { it.location })

    @Id
    Location location
    String owner
    int timesClicked


}
 def onInteract = { PlayerInteractEvent e ->
        if (!e.hasBlock()) return
        if (!e.hasItem() || e.getItem().getType() != Material.STICK) return
        def clicked = e.getClickedBlock().getLocation()
        def player = e.player
        def machine = Machine.CACHE.getCached(clicked)
                ?: new Machine(owner: player.name, location: clicked)
        machine.timesClicked++
        player.sendMessage("$machine")
        machine.cache() // if not cached, cache it
    }

Cache Options

First, let's explain the Cache constructor: static final Cache<Location, Machine> CACHE = new Cache<>(Machine, { it.location }) The first parameter it's our domain object class, the second one is its key. @CacheOptions

  • loadAllOnEnable() - load all objects into cache on onEnable(), default false
  • saveAllOnDisable() - save all cached objects on onDisable(), default true
  • autoSave() - save all cached objects periodically, default true
  • autoSaveDelay() - the delay of our autosave in minutes, default 30
  • loadOnJoin() - load a object into cache if is found a object with the key being the player's name, default false (ONLY FOR PLAYERS) (Useful for User)
  • saveOnQuit() - same as above, default false