1. Powinieneś użyć tzn. connection pool, czyli połączyć się z bazą x razy (najlepiej do ustawienia w configu). I później używać połączeń naprzemiennie, zapisując je w liście. Odciąży to "jedno połączenie" i dzięki temu, jeżeli będziesz wykonywał duże zapytanie, albo pare małych to zawsze zostanie wybrane połączenie, które nie jest zablokowane dla tego zapytania.
2. Używasz #prepareStatement, po czym nie używasz najważniejszej funkcji tej metody, czyli parametrów. W zapytaniu używasz znaków zapytania (?), każdy znak zapytania jest indeksowany od 1 w górę. Później dla każdego parametru używasz metody PreparedStatement#setString(1, uuid) analogicznie #setInt(2, kills), #setLong(3, lastLogin) itd..
3. Konwencja nazewnictwa w sql (w pytaniu jest mysql, ale dotyczy to też sqlite i wielu innych języków sql) - https://stackoverflow.com/a/62706057
4. Co do nazewnictwa to, niektóre nazwy atrybutów masz w liczbie mnogiej, a inne w pojedynczej - warto się zdecydować (Kills/BlockPlaced)
5. Dobrą rzeczą jest używanie cache. Z tego co widzę to jest w porządku całkiem zakodzony, trochę dziwnie, ale jeżeli działa to spoko.
Ogólnie rzecz ujmując masz pojęcie i całkiem dobrze sobie radzisz. Jeżeli są to Twoje początki to prawdopodobnie tak wyglądałby kod osoby, która naczytała się poradników i oglądnęła jakieś kursy także jesteś na dobrej ścieżce rozwoju. Nic tylko życzyć powodzenia.
ps co do 2 to warto sobie przygotować metody select/update(String zapytanie, String ... argumenty) i później w pętli setować sobie wartości dla czystej wygody