Performantes Speichern von HashMaps

Hallo liebe Forengemeinde,

ich stehe mal wieder vor einem Problem (immer diese doofen Datenbanken… :ka:).
Ich erkläre es mal anhand eines Beispieles meiner momentanen Situation:

Enum:

public enum Flag {

  FLAG1(0),
  FLAG2(1),
  ...;

  private int id;

  private Flag(int id) {
    this.id = id;
  }

  public int getFlagID() {
    return this.id;
  }
}```

Klasse:

public void saveStuff(HashMap<Flag, Boolean> flagStatus, HashMap<Flag, List> flags) {
// Wie speicher ich diese nun effizient?
}```

Ich habe schon einige Male versucht, die Map auf einen String aufzuteilen und Key,Value später aufzusplitten (splitted[0] & splitted[1]).
Jedoch bin ich mir nicht wirklich sicher, ob es sinnvoll ist, die HashMap als “text” in die Datenbank zu speichern. Nur wie soll ich das denn auch machen, wenn ich nun HashMap<Flag, List<String>> flags habe? Wie soll ich denn die List<String> auch noch splitten?

Und bevor jemand fragt: Nein, ich habe nicht die Möglichkeit, die HashMap in eine eigene Tabelle zu speichern. Erstens deshalb, weil die HashMap’s in meinem Fall wichtige Informationen FÜR andere Werte in der Tabelle beinhalten, und zweitens weil man soweit ich weiß nicht wirklich gut List splitten kann…

Danke im Vorraus!

Mit freundlichen Grüßen,
Panjab.

Wenn du die Values aus der HashMap in der DB nicht brauchst kannst du sie doch einfach als BLOB speichern. HashMap ist serialisierbar.

Also Flag ist klar, die Map<Flag,Boolean> auch (beachte: Interface, nicht Implementierung). Was die Map<Flag, List> soll, erschließt sich nicht. Was steht denn in dem einzelnen String drinnen? Und für was wird eine Liste davon gebraucht? Und in welcher Beziehung stehen die beiden Maps zueinander. Ist in einer relationalen DB ja keine ganz unwichtige Frage und ne Beziehung wirds ja geben, sonst würdest Du sie ja nicht in derselben Methode speichern wollen.

Was meinst du genau mit (beachte: Interface, nicht Implementierung)?
Ich erkläre mal die HashMaps:

Die erste HashMap, HashMap<Flag, Boolean> stellt klar, ob eine Flag aktiviert ist oder nicht.
Die zweite HashMap, HashMap<Flag, List<String>> gibt die Personen an, welche die Flag nutzen dürfen. Daher die List.

Die Beziehung sollte soweit geklärt sein, oder?
Und wegen dem Speichern noch eine Anmerkung: Man kann sich meine Tabelle in etwa so vorstellen:

database → regions
id | name | owner | volume | flags | flaguser

gruß

Der Sinn deiner HashMaps lässt sich ohne die genauen Umstände deines Szenarios ohnehin nicht erkennen. Ich hab hier noch einen link falls du nicht weit weißt von was ich gesprochen habe: http://javaprogramming.language-tutorial.com/2012/10/java-object-as-blob.html

@bERt0r

Ich habe mir deinen Link angeschaut und gemerkt, jedoch habe ich eine etwas “andere” Methode.
Ich habe in meinem DatabaseHandler, wie in diesem Forum bereits gelöst, folgende Methode:

	public synchronized List<Map<String, Object>> getResults( String sql ) throws Exception {
		
		if ( !isAvailable() ) throw new Exception("No active database connection found!
");
		
		List<Map<String, Object>> columns = new ArrayList<>();
		
		ResultSet resultSet = getConnection().prepareStatement(sql).executeQuery();
		ResultSetMetaData metaData = resultSet.getMetaData();
		
		int columnCount = metaData.getColumnCount();
		
		while (resultSet.next()) {
			
			Map<String, Object> column = new LinkedHashMap<>(columnCount);
			
			for (int i = 1; i <= columnCount; i++) {
				column.put(metaData.getColumnName(i), resultSet.getObject(i));
			}
			
			columns.add(column);
		}
		
		return columns;
	}```

Ich bin mir nicht ganz sicher, ob man somit auch einen BLOB auslesen kann.

Zu meinem momentanen Szenario:
Ich entwickle für die Minecraft-ServerAPI "Bukkit" ein Plugin, welches Regionen (bei mir Cuboids) in eine DB speichern soll. Dazu habe ich diesen Konstruktor:

protected Cuboid(String name, int id, int ownerID, CuboidType cuboidType, 
				Location minLocation, Location maxLocation, World world, String enterMessage, String leaveMessage, 
				HashMap<Flag, Boolean> flags, HashMap<Flag, List<String>> flaguser) {

    // ... stuff
    }```

Die letzten 2 Argumente sind die beschriebenen HashMaps.
Diese muss ich nun in meinem CuboidHandler in folgender Methode irgendwie in die DB speichern:

	public void registerCuboid(String name, int owner, CuboidType type, Location min, Location max, String enterMsg, String leaveMsg, HashMap<Flag, Boolean> flags, HashMap<Flag, List<String>> flaguser) {
		if (name == null || owner < 0 || type == null || min == null || max == null || enterMsg == null || leaveMsg == null || events == null || flags == null) return;
		if (existsCuboid(name)) return;
		
		try {
			
			int id = generateID();
			int typeID = type.getTypeID();
			String world = min.getWorld().getName();
			String minLoc = min.getBlockX() + "," + min.getBlockY() + "," + min.getBlockZ() + "," + min.getYaw() + "," + min.getPitch();
			String maxLoc = max.getBlockX() + "," + max.getBlockY() + "," + max.getBlockZ() + "," + max.getYaw() + "," + max.getPitch();
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}```

Es ist schon alles andere "vorbereitet", außer die beiden HashMaps, da ich mir überhaupt nicht sicher bin, wie ich das am besten umsetze. Der von dir empfohlene BLOB sollte dafür ja geeignet sein - aber wie mache ich das am besten?

gruß

Ich meine damit, dass Du hier bei der Definition von Methoden nicht mit konkreten Implementierungen (HashMap), sondern mit Interfaces (Map) arbeiten solltest. Deswegen habe ich die Fragen absichtlich mit Map formuliert. Gerade bei Map<Flag,Boolean> würde sich nämlich als viel performantere Implementierungsalternative die EnumMap anbieten, die Du so nicht nutzen kannst, weil Du Dich unnötigerweise auf eine Implementierung (HashMap) festlegst.

Zum Datenmodell noch eine Frage: Wie frei bist Du da bei einer Umgestaltung? Person hört sich nach einer eigenen Entity an und wenn Du eine bestimmte Kombination von Flags identifizieren willst, die von einer bestimmten Gruppe Personen benutzt wird/werden darf, wäre da evtl auch diese FlagKombination eine eigente Entity wert.

Edit: Habe gerade Deinen letzten Post überflogen und wegen Komplexität nicht nachvollzogen. Vielleicht passt meine Frage damit nicht. Ggf. darum einfach ignorieren. Ich steig dann hier aus.

Ich versteh auch nicht wo das Problem liegt. Ich hab dir einen Link gepostet mit einem Beispiel das ein beliebiges Java Objekt als BLOB in eine DB speichert und diesen BLOB dann wieder ausliest. Wenn du dich da wo nicht auskennst dann sag das, wie dein Code aussieht interresiert hier nicht weil da das Problem nicht liegt.

@bERt0r

Der von dir empfohlene BLOB sollte dafür ja geeignet sein - aber wie mache ich das am besten?

Habe ich bereits :wink:
Aber ich habe das Problem bereits gelöst, ich habe meine Klasse durch Methoden erweitert, welche in einen byte umwandeln.

Danke trotzdem. :slight_smile: