You are not logged in.

  • Login
Bitte besucht unser neues Forum unter https://forum.nitrado.net | Please visit our new Forum at https://forum.nitrado.net

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

1

Monday, July 7th 2014, 6:37pm

[Java] SQLite Libary v1.7 - Leichtere Alternative zu MySQL

SQLite Libary

Hey Leute,
Ich will euch heute meine SQLite Libary vorstellen. Diese besteht aus 3 Klassen und vereinfacht euch die Arbeit mit SQLite.


Voraussetzungen:


Nutzungsweise:
Um mit einer SQLite Datenbank arbeiten zu können, benötigen wir zuerst eine Datenbank Instanz. Diese kann man folgend initialisieren:

Java source code

1
Database dbase = new Database(File database);

  • database = Datei der Datenbank


Somit haben wir nun eine Datenbank-Instanz. Um jetzt auf die Tabellen der Datenbank zugreifen zu können, müssen wir zuerst eine Verbindung herstellen. Dies tun wir folgend:

Java source code

1
dbase.openConnection();

Nicht zu vergessen die Exceptions abzufangen ;)

Nun können wir uns an die Tabellen ran machen. Um eine Instanz einer Tabelle zu holen, tun wir folgendes:

Java source code

1
Table table = dbase.getTable(String tablename);

  • tablename = Name der Tabelle

Wenn wir aber an der Tabelle Änderungen vornehmen wollen, dann müssen wir noch die Spalten und Datentypen übergeben. Hierfür müssen wir folgendes ergänzen:

Java source code

1
2
3
String[] columns = { "name", "age", "city", "country", "photo" };
DataType[] types = { DataType.TEXT, DataType.INT, DataType.TEXT, DataType.TEXT, DataType.BLOB };
Table table = dbase.getTable("portal_userdata", columns, types);

Somit können wir nun auch Änderungen an der Tabelle vornehmen. Wenn man nur aus der Tabelle lesen will, dann wird nur die erste Methode benötigt.

Nun wollen wir gucken, ob die Tabelle überhaupt existiert und erstellen dann eine neue Tabelle entsprechend. Dies tun wir folgend:

Java source code

1
2
3
4
if(!table.exists())
{
     table.create();
}


Jetzt fügen wir einen neuen Benutzer in die Tabelle hinzu:

Java source code

1
2
3
4
5
6
7
8
9
Object[] values = { "Max Mustermann", 20, "Frankfurt am Main", "Deutschland", photoFile.getBytes() };
if(table.contains("name", "Max Mustermann"))
{
     table.updateEntry(values, "name", "Max Mustermann");
}
else
{
     table.insertEntry(values);
}



Zu guter letzt holen wir uns aus der Tabelle das Alter von unserem Max Mustermann raus:

Java source code

1
int age = table.getAge("age", "name", "Max Mustermann");



Das waren die Grundlagen zu der Nutzungsweise dieser Libary. Falls ihr irgendwelche Probleme oder Fragen habt, dann schreibt sie hier rein :)


Download:



Viel Spaß mit der Libary,
David (Codebucket.de) 8)

This post has been edited 3 times, last edit by "BlazeMania" (Jul 19th 2014, 4:09pm)


BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

2

Monday, July 7th 2014, 6:41pm

Nutzt du jetzt auch PreparedStatements?
Standard Standart eines Flamingos ist einbeinig.

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

3

Monday, July 7th 2014, 6:42pm

@BtoBastian:
Bei SQLite ist es mir nicht gelungen mit PreparedStatements zu arbeiten :( Falls du die Lösung für das Problem wüsstest, würde ich mich freuen wenn du mir die Lösung schicken könntest :)

MfG David

BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

4

Monday, July 7th 2014, 6:45pm

SQLite und MySQL sind doch exakt gleich zu nutzen?
Nur die Verbindung muss man anders 'aufbauen'.

Java source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package de.oppermann.bastian.lib.storage;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Class for SQL-management.
 */
public abstract class SQLConnector {

	protected Connection connection;
	protected boolean succeeded = false;
	protected String database;

	static {
		try {
			Class.forName("org.sqlite.JDBC");
		} catch (ClassNotFoundException e) {
			System.err.println("Could not find JDBC-driver!");
			e.printStackTrace();
		}
	}

	/**
	 * Gets a {@link Statement}.
	 * <p>
	 * Beware of SQL injection! Use a PreparedStatement instead.
	 * 
	 * @return A Statement.
	 * @throws SQLException
	 * @see {@link Connection#createStatement()}
	 */
	public Statement getStatement() throws SQLException {
		return connection.createStatement();
	}

	/**
	 * Prepares a statement.
	 * 
	 * @param sql The sql-command.
	 * @return A prepared statement.
	 * @throws SQLException
	 * @see {@link Connection#prepareStatement(String)}
	 */
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		if(sql == null)
			throw new IllegalArgumentException("sql cannot be null");
		return connection.prepareStatement(sql);
	}

	/**
	 * Closes a connection.
	 * 
	 * @throws SQLException 
	 */
	public void closeConnection() throws SQLException {
		if(connection != null && !connection.isClosed())
			connection.close();
	}
	
	/**
	 * Connects to the database.
	 * 
	 * @throws SQLException
	 */
	protected abstract void connect() throws SQLException;

}


Java source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package de.oppermann.bastian.lib.storage;

import java.io.File;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.bukkit.plugin.java.JavaPlugin;

/**
 * Class to connect to a SQLite-database.
 */
public class SQLiteConnector extends SQLConnector {

	private final String DB_PATH;

	/**
	 * Class constructor.
	 * 
	 * @param plugin The plugin.
	 * @param filename The file name.
	 * @throws SQLException
	 */
	public SQLiteConnector(JavaPlugin plugin, String filename) throws SQLException {
		if(plugin == null)
			throw new IllegalArgumentException("plugin cannot be null");
		if(filename == null)
			throw new IllegalArgumentException("filename connot be null");
		DB_PATH = plugin.getDataFolder().getPath() + "/" + filename;
		File f = new File(plugin.getDataFolder().getPath());
		f.mkdirs();
		connect();
		succeeded = connection != null;
	}

	/*
	 * (non-Javadoc)
	 * @see de.oppermann.bastian.lib.storage.SQLConnector#connect()
	 */
	@Override
	protected void connect() throws SQLException {
		if (connection != null)
			return;
		connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				try {
					closeConnection();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}

}


Java source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package de.oppermann.bastian.lib.storage;

import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * Class to connect to a MySQL-database.
 */
public class MySQLConnector extends SQLConnector {

	private String host;
	private String port;
	private String database;
	private String user;
	private String pass;

	/**
	 * Class constructor.
	 * 
	 * @param host The server host.
	 * @param port The server port.
	 * @param database The name of the database.
	 * @param user The name of the user.
	 * @param pass The password.
	 * @throws SQLException
	 */
	public MySQLConnector(String host, String port, String database, String user, String pass) throws SQLException {
		if(host == null)
			throw new IllegalArgumentException("host cannot be null");
		if(port == null)
			throw new IllegalArgumentException("port cannot be null");
		if(database == null)
			throw new IllegalArgumentException("database cannot be null");
		if(user == null)
			throw new IllegalArgumentException("user cannot be null");
		if(pass == null)
			throw new IllegalArgumentException("pass cannot be null");
		this.host = host;
		this.port = port;
		this.database = database;
		this.user = user;
		this.pass = pass;
		connect();
		succeeded = connection != null;
	}

	/*
	 * (non-Javadoc)
	 * @see de.oppermann.bastian.lib.storage.SQLConnector#connect()
	 */
	@Override
	protected void connect() throws SQLException{
		connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?user=" + user + "&password=" + pass);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				try {
					closeConnection();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}

}


// EDIT
Beispiel für Verwendung:

Spoiler Spoiler


Java source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package de.oppermann.bastian.lib.economy;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.UUID;

import org.bukkit.Bukkit;

import de.oppermann.bastian.lib.Main;
import de.oppermann.bastian.lib.storage.SQLConnector;
import de.oppermann.bastian.lib.storage.SQLiteConnector;

/**
 * Intern required class.
 * <p>
 * Do not call any method of it!
 * This class is used for internal purposes and can lead to serious errors if it is used.
 */
public class EconomyPlayer {

	private static HashMap<UUID, EconomyPlayer> economyPlayers = new HashMap<>();
	
	private static final EconomyDatabase DATABASE = new EconomyDatabase();
	
	private final UUID _UUID;
	
	private int money;
	private int rubies;
	
	private EconomyPlayer(UUID uuid, int money, int rubies) {
		economyPlayers.put(uuid, this);
		
		this._UUID = uuid;
		this.money = money;
		this.rubies = rubies;
	}

	/**
	 * Gets the money of the player.
	 * 
	 * @return The money.
	 */
	public int getMoney() {
		return money;
	}

	/**
	 * Sets the money of the player.
	 * 
	 * @param money The money to set.
	 */
	public void setMoney(int money) {
		this.money = money;
		DATABASE.setMoney(_UUID, money);
	}

	/**
	 * Gets the rubies of the player.
	 * 
	 * @return The rubies.
	 */
	public int getRubies() {
		return rubies;
	}

	/**
	 * Sets the rubies of the player.
	 * 
	 * @param rubies The rubies to set.
	 */
	public void setRubies(int rubies) {
		this.rubies = rubies;
		DATABASE.setRubies(_UUID, rubies);
	}

	/**
	 * Gets the uuid of the player
	 * 
	 * @return The uuid of the player.
	 */
	public UUID getUniqueId() {
		return _UUID;
	}
	
	/**
	 * Intern required method.
	 * <p>
	 * Do not call it!
	 * This method is used for internal purposes and can lead to serious errors if it is called.
	 */
	public static void closeConnection() {
		try {
			DATABASE.db.closeConnection();
		} catch (SQLException e) {
			// should not happen
			e.printStackTrace();
		}
	}
	
	/**
	 * Gets an instance of an EconomyPlayer.
	 * 
	 * @param uuid The uuid of the player.
	 * @return The EconomyPlayer.
	 */
	public static EconomyPlayer getEconomyPlayer(UUID uuid) {
		if (economyPlayers.containsKey(uuid)) {
			return economyPlayers.get(uuid);
		} else {
			return createNewEconomyPlayer(uuid, 0, 0);
		}
	}
	
	private static EconomyPlayer createNewEconomyPlayer(UUID uuid, int money, int rubies) {
		EconomyPlayer economyPlayer = new EconomyPlayer(uuid, money, rubies);
		DATABASE.createEconomyPlayer(economyPlayer);
		return economyPlayer;
	}
	
	/** private static class for database management */
	private static class EconomyDatabase {
		
		private SQLConnector db;
		
		private EconomyDatabase() {
			try {
				db = new SQLiteConnector(Main.getInstance(), "money.db");
				db.getStatement().executeUpdate("CREATE TABLE IF NOT EXISTS playermoney (uuid CHAR(36), money INT, rubies INT);");
				ResultSet rs = db.getStatement().executeQuery("SELECT * FROM playermoney");
				while (rs.next()) {
					new EconomyPlayer(UUID.fromString(rs.getString("uuid")), rs.getInt("money"), rs.getInt("rubies"));
				}
			} catch (SQLException e) {
				System.out.println("Failed to connect to economy database 'money.db'!\nshutting down the server!");
				e.printStackTrace();
				Bukkit.shutdown();
			}
		}
		
		private void createEconomyPlayer(EconomyPlayer economyPlayer) {
			try {
				PreparedStatement stmt = db.prepareStatement("INSERT INTO playermoney (uuid, money, rubies) VALUES (?, ?, ?);");
				stmt.setString(1, economyPlayer.getUniqueId().toString());
				stmt.setInt(2, economyPlayer.getMoney());
				stmt.setInt(3, economyPlayer.getRubies());
				stmt.execute();
			} catch (SQLException e) {
				// will hopefully never happen
				e.printStackTrace();
			}
		}
		
		private void setRubies(UUID uuid, int rubies) {
			try {
				PreparedStatement stmt = db.prepareStatement("UPDATE playermoney SET rubies = ? WHERE uuid = ?");
				stmt.setString(2, uuid.toString());
				stmt.setInt(1, rubies);
				stmt.execute();
			} catch (SQLException e) {
				// will hopefully never happen
				e.printStackTrace();
			}			
		}

		private void setMoney(UUID uuid, int money) {
			try {
				PreparedStatement stmt = db.prepareStatement("UPDATE playermoney SET money = ? WHERE uuid = ?");
				stmt.setString(2, uuid.toString());
				stmt.setInt(1, money);
				stmt.execute();
			} catch (SQLException e) {
				// will hopefully never happen
				e.printStackTrace();
			}
		}
		
	}
	
}

Standard Standart eines Flamingos ist einbeinig.

This post has been edited 2 times, last edit by "BtoBastian" (Jul 7th 2014, 7:03pm)


BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

5

Monday, July 7th 2014, 7:10pm

@BtoBastian:
Okay auf einmal scheint es zu funktionieren:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[test_userdata] Tablesize now: 16
Values of User Codebucket: 
username: Codebucket, password: password_das_eh_die_nsa_kennt, level: 9000, uuid: 58968.0, online: false
+++ TOP 10 USERS WITH MOST LEVELS +++
1. Codebucket: 281
2. user514: 47
3. user203: 46
4. user628: 45
5. user337: 42
6. user883: 39
7. user237: 35
8. user240: 35
9. user11: 16
10. user956: 7
+++ END OF THE LIST +++

Table(database=F:\Server\Developement\Eclipse\SQLite API\user\database.db, name=test_userdata, columns=[`username`, `password`, `level`, `uuid`, `online`], types=[TEXT, TEXT, INT, FLOAT, BOOLEAN])
Database(file=F:\Server\Developement\Eclipse\SQLite API\user\database.db)


Update wird gleich hochgeladen :)
//EDIT: Update verfügbar, nun werden PreparedStatements vollständig unterstützt :)

This post has been edited 1 times, last edit by "BlazeMania" (Jul 7th 2014, 7:38pm)


ketrwu14

Moderator

  • "ketrwu14" is male

Posts: 1,430

Thanks: 2

  • Send private message

6

Monday, July 7th 2014, 7:56pm

Hmm SQLite wollte ich mir schon immer mal ansehen. Hab so einige Plugins für die SQLite besser als Configs sind und MySQL war mir dafür meist zu überzogen.

PS: if(table.contains("name", "Max Mustermann")

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

7

Monday, July 7th 2014, 7:58pm

@ketrwu14:
Danke, der selbe Grund, weshalb ich meine MySQL Libary auch für SQLite überarbeitet habe :)

BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

8

Monday, July 7th 2014, 8:05pm

Ich verwende inzwischen auch nur noch SQLite.
Ist angenehmer als MySQL, da man dort ne richtige Datei hat, die man kopieren, bearbeiten, versenden, löschen, ... kann.
Für BackUps viel angenehmer. :-)
Standard Standart eines Flamingos ist einbeinig.

ketrwu14

Moderator

  • "ketrwu14" is male

Posts: 1,430

Thanks: 2

  • Send private message

9

Saturday, July 12th 2014, 11:36am

Also hab die Libary gestern mal in ein neues Plugin eingebaut und hat alles super funktioniert. Was glaube ich fehlte war eine Methode um einen bestimmten Eintrag zu löschen, kann auch sein dass ich die nur über sehen hab xD

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

10

Saturday, July 12th 2014, 2:28pm

@ketrwu14:
Oder ich sie vergessen habe zu implementieren. Updates folgen :)

crafter75

User / Kunde

Posts: 170

  • Send private message

11

Saturday, July 12th 2014, 4:25pm

also ist das wie MySQL? Und damit kann man Statistiken & ein Ranking machen?

BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

12

Saturday, July 12th 2014, 4:55pm

Ein einfaches Ja hätte denke ich gereicht.
(Auf Bukkit-Plugins) mal ganz allgemein gesagt:
- Du willst die Daten auf mehreren Servern nutzen, bzw. auf der Homepage anzeigen --> MySQL
- Du brauchst die Daten weder auf anderen Servern, noch auf einer Homepage, sondern einfach nur auf dem Server --> SQLite

Nutzen beide SQL, ist also leicht zwischen beiden zu wechseln.
Standard Standart eines Flamingos ist einbeinig.

crafter75

User / Kunde

Posts: 170

  • Send private message

13

Saturday, July 12th 2014, 4:59pm

Quoted

Du willst die Daten auf mehreren Servern nutzen


jo (BungeeCord) also doch MySQL? ?(

BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

14

Saturday, July 12th 2014, 5:27pm

Stell es dir einfach wie ne Config vor.
Ist ne Datei auf'n Server.
Ich kenn mich mit BungeeCord nicht so gut aus, aber ich vermute ja, MySQL wäre da die bessere Wahl.
Standard Standart eines Flamingos ist einbeinig.

crafter75

User / Kunde

Posts: 170

  • Send private message

15

Saturday, July 12th 2014, 5:39pm

okay Danke :)

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

16

Saturday, July 12th 2014, 5:41pm

Ich stelle es mir so vor:

Bukkit Plugin:
- Mehrere Server, gleiche Daten oder Website -> MySQL
- Große Datenspeicherungen, nur ein Server -> SQLite

BungeeCord:
- Nur auf einem BungeeCord -> SQLite
- Auf mehreren Bungees oder Website -> MySQL

@BtoBastian:
BungeeCord ist ein Proxy, was mehrere Server verbindet und sie verwaltet, inkl. Spieler und Informationen. Somit muss man den Spielern nur eine Serveradresse geben, unter der das Proxy läuft und die Spieler können von dort auf andere Server verbinden. BungeeCord enthält auch eine API um Beispielsweise Spielern Nachrichten InGame zu schicken oder auf andere Server zu "verschieben".

MfG David

//PS: @ketrwu14: Du kannst vorerst mal die Daten manuell löschen, indem du die Datenbank-Instanz der Tabelle mit Table#getDatabase holst und da Database#executeQuery benutzt ;)

ketrwu14

Moderator

  • "ketrwu14" is male

Posts: 1,430

Thanks: 2

  • Send private message

17

Saturday, July 12th 2014, 5:51pm

Jupp hab ich ich auch glaube ich so gemacht xD

BtoBastian

Moderator

  • "BtoBastian" is male

Posts: 3,612

Occupation: Softwareentwickler

  • Send private message

18

Saturday, July 12th 2014, 6:35pm

@BtoBastian:
BungeeCord ist ein Proxy, was mehrere Server verbindet und sie verwaltet, inkl. Spieler und Informationen. Somit muss man den Spielern nur eine Serveradresse geben, unter der das Proxy läuft und die Spieler können von dort auf andere Server verbinden. BungeeCord enthält auch eine API um Beispielsweise Spielern Nachrichten InGame zu schicken oder auf andere Server zu "verschieben".

Soviel ist mir auch klar, nur wie es mit der Datenspeicherung aussieht war ich mir nicht sicher.
Jann ja sein, dass es ein "Root"-Verzeichnis gibt auf das alle Server Zugriff haben. Da hätte man dann die SQLite-Datei ablegen können.
Standard Standart eines Flamingos ist einbeinig.

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

19

Saturday, July 12th 2014, 7:31pm

@BtoBastian:
Wenn man schlau genug ist, dann hätte man ein Verzeichnis angelegt, an den jeder Server zugriff hat und entsprechend den Pfad zur Datei angegeben ;) Das würde halt noch gehen, dass der Server auf die Oberverzeichnisse zugreifen kann :)

BlazeMania

User / Kunde

  • "BlazeMania" is male
  • "BlazeMania" started this thread

Posts: 1,299

Location: Berlin

Occupation: Schüler (Gymnasium)

  • Send private message

20

Friday, July 18th 2014, 1:13pm

#bump

Bitte besucht unser neues Forum unter https://forum.nitrado.net| Please visit our new Forum at https://forum.nitrado.net