Browse Source

Avancement BDD

Arthur Brandao 5 năm trước cách đây
mục cha
commit
7809eb8dc7
6 tập tin đã thay đổi với 305 bổ sung20 xóa
  1. 73 2
      src/db/Database.java
  2. 1 1
      src/db/Mapper.java
  3. 1 0
      src/db/Persistable.java
  4. 205 15
      src/db/Table.java
  5. 13 0
      src/db/table/EspaceTable.java
  6. 12 2
      src/servlets/TestDb.java

+ 73 - 2
src/db/Database.java

@@ -1,13 +1,21 @@
 package db;
 
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.logging.Logger;
 
+import db.table.EspaceTable;
+import entity.Espace;
+
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 
 public class Database {
@@ -20,6 +28,12 @@ public class Database {
 		unset();
 		setup();
 		execute("Insert into Espace(LIBELLE) Values('test')");
+		//execute("Insert into Espace(LIBELLE) Values('test')");
+		EspaceTable et = EspaceTable.getInstance();
+		Espace e = new Espace();
+		e.id = 8;
+		e.libelle = "bjr";
+		et.save(e);
 	}
 	
 	public static void ini() {
@@ -73,7 +87,7 @@ public class Database {
 	
 	public static boolean query(String sql) {
 		try(Statement st = db.createStatement()) {
-			ResultSet result = st.executeQuery(sql);
+			st.executeQuery(sql);
 			return true;
 		} catch (SQLException | IllegalStateException e) {
 			LOGGER.warning(e.getMessage());
@@ -81,7 +95,7 @@ public class Database {
 		}
 	}
 	
-	public static <T extends Persistable> Optional<T> query(String sql, Mapper<T> mapper) {
+	public static <T> Optional<T> query(String sql, Mapper<T> mapper) {
 		try(Statement st = db.createStatement()) {
 			ResultSet result = st.executeQuery(sql);
 			T obj = mapper.map(result);
@@ -92,6 +106,21 @@ public class Database {
 		}
 	}
 	
+	public static <T> Optional<T> query(String sql, List<Object> params, Mapper<T> mapper) {
+		try(PreparedStatement st = db.prepareStatement(sql)) {
+			int i = 1;
+			for(Object param : params) {
+				st.setObject(i++, param);
+			}
+			ResultSet result = st.executeQuery();
+			T obj = mapper.map(result);
+			return Optional.of(obj);
+		} catch (SQLException | IllegalStateException e) {
+			LOGGER.warning(e.getMessage());
+			return Optional.empty();
+		}
+	}
+	
 	public static boolean execute(String sql) {
 		try(Statement st = db.createStatement()) {
 			int result = st.executeUpdate(sql);
@@ -102,6 +131,48 @@ public class Database {
 		}
 	}
 	
+	public static boolean execute(String sql, List<Object> params) {
+		try(PreparedStatement st = db.prepareStatement(sql)) {
+			int i = 1;
+			for (Object param : params) {
+				st.setObject(i++, param);
+			}
+			int result = st.executeUpdate();
+			return result == 1;
+		} catch (SQLException e) {
+			LOGGER.warning(e.getMessage());
+			return false;
+		}
+	}
+	
+	public static Map<String, Object> insert(String sql, List<Object> params, String[] idField) {
+		Map<String, Object> ids = new HashMap<>();
+		try(PreparedStatement st = db.prepareStatement(sql, idField)) {
+			// Ajout parametre
+			int i = 1;
+			for(Object param : params) {
+				st.setObject(i++, param);
+			}
+			// Execution requete
+			int result = st.executeUpdate();
+			if(result != 1) {
+				return ids;
+			}
+			// Recuperation des ids genere
+			ResultSet rs = st.getGeneratedKeys();
+			rs.next();
+			i = 1;
+			for (String field : idField) {
+				ids.put(field, rs.getObject(i));
+				i++;
+			}
+			return ids;
+		} catch (SQLException e) {
+			LOGGER.warning(e.getMessage());
+			return ids;
+		}
+	}
+	
 	public static boolean isSet() {
 		return query("Select * From Espace");
 	}

+ 1 - 1
src/db/Mapper.java

@@ -3,7 +3,7 @@ package db;
 import java.sql.ResultSet;
 
 @FunctionalInterface
-public interface Mapper<T extends Persistable> {
+public interface Mapper<T> {
 
 	public T map(ResultSet data);
 	

+ 1 - 0
src/db/Persistable.java

@@ -3,4 +3,5 @@ package db;
 public interface Persistable {
 
     long getId();
+    
 }

+ 205 - 15
src/db/Table.java

@@ -1,10 +1,15 @@
 package db;
 
+import java.util.List;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 
 import db.annotation.DbField;
@@ -13,24 +18,48 @@ import db.annotation.DbTable;
 
 public abstract class Table<T extends Persistable> {
 	
-	protected Map<Long, T> cacheMap = new HashMap<>();
+	private Map<Long, T> cacheMap = new HashMap<>();
 	
 	public Optional<T> findById(long id) {
 		if (cacheMap.containsKey(id)) {
 			return Optional.of(cacheMap.get(id));
 		}
-		Optional<T> obj = getFromDb(id);
+		Optional<T> obj = getFromDbById(id);
 		if(obj.isPresent()) {
 			cache(obj.get());
 		}
 		return obj;
 	}
 	
+	public T getById(long id) {
+		Optional<T> opt = findById(id);
+		if(opt.isEmpty()) {
+			return null;
+		}
+		return opt.get();
+	}
+	
+	public List<T> getByField(String fieldname, Object value) {
+		List<T> list = getFromDbByField(fieldname, value);
+		list.forEach(elt -> cache(elt));
+		return list;
+	}
+	
+	public List<T> getWhere() {
+		return null;
+	}
+	
+	public List<T> getAll() {
+		List<T> list = getAllFromDb();
+		list.forEach(elt -> cache(elt));
+		return list;
+	}
+	
 	public T refresh(long id) {
 		if (!cacheMap.containsKey(id)) {
 			throw new IllegalArgumentException("Entity is not load, can't refresh");
 		}
-		Optional<T> optObj = getFromDb(id);
+		Optional<T> optObj = getFromDbById(id);
 		if(optObj.isEmpty()) {
 			throw new IllegalStateException("Unable to find entity in the database");
 		}
@@ -49,6 +78,7 @@ public abstract class Table<T extends Persistable> {
 		} else {
 			insert(obj);
 		}
+		cache(obj);
 	}
 	
 	public final void delete(long id) {
@@ -65,32 +95,42 @@ public abstract class Table<T extends Persistable> {
 		} else {
 			cacheMap.put(obj.getId(), obj);
 		}
+		//System.out.println("Cache size: " + cacheMap.size());
+		//cacheMap.forEach((key, val) -> System.out.println("Cache: " + key));
 	}
 	
-	private Optional<T> getFromDb(long id) {
+	private DbTable getDbTableAnnotation() {
 		Class<?> clazz = this.getClass();
 		// Recupération info anotation DbTable
 		if (!clazz.isAnnotationPresent(DbTable.class)) {
 			throw new IllegalStateException("Unable ton find DbTable annotation");
 		}
-		DbTable dbTable = clazz.getAnnotation(DbTable.class);
+		return clazz.getAnnotation(DbTable.class);
+	}
+	
+	private Optional<T> getFromDbById(long id) {
+		DbTable dbTable = getDbTableAnnotation();
 		// Cherche l'id
 		String idField = null;
 		for(Field field : dbTable.entity().getFields()) {
-			if(field.isAnnotationPresent(DbId.class)) {
-				if(field.isAnnotationPresent(DbField.class)) {
-					idField = field.getAnnotation(DbField.class).name();
-				} else {
-					throw new IllegalStateException("Unable to find DbField annotation on id");
-				}
+			if(!field.isAnnotationPresent(DbId.class)) {
+				continue;
+			}
+			// Lecture du nom de l'id dans la base
+			if(field.isAnnotationPresent(DbField.class)) {
+				idField = field.getAnnotation(DbField.class).name();
+			} else {
+				throw new IllegalStateException("Unable to find DbField annotation on id");
 			}
 		}
 		if (idField == null) {
 			throw new IllegalStateException("Unable to find find DbField annotation");
 		}
 		// Requete sql
-		String sql = "Select * From " + dbTable.name() + " Where " + idField + " = " + id;
-		Optional<T> result = Database.query(sql, rs -> {
+		String sql = "Select * From " + dbTable.name() + " Where " + idField + " = ?";
+		List<Object> params = new ArrayList<>();
+		params.add(id);
+		Optional<T> result = Database.query(sql, params, rs -> {
 			try {
 				T obj = (T) dbTable.entity().getConstructor().newInstance();
 				rs.next();
@@ -109,12 +149,162 @@ public abstract class Table<T extends Persistable> {
 		return result;
 	}
 	
+	private List<T> getFromDbByField(String fieldname, Object value) {
+		DbTable dbTable = getDbTableAnnotation();
+		// Requete sql
+		String sql = "Select * From " + dbTable.name() + " Where " + fieldname + " = ?";
+		List<Object> params = new ArrayList<>();
+		params.add(value);
+		Optional<List<T>> result = Database.query(sql, params, rs -> {
+			try {
+				List<T> list = new ArrayList<>();
+				while(rs.next()) {
+					T obj = (T) dbTable.entity().getConstructor().newInstance();
+					for(Field field : dbTable.entity().getFields()) {
+						if(!field.isAnnotationPresent(DbField.class)) {
+							continue;
+						}
+						obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
+					}
+					list.add(obj);
+				}
+				return list;
+			} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
+				throw new IllegalStateException("Unable to map value to the entity");
+			}
+		});
+		// Return
+		if(result.isEmpty()) {
+			return new ArrayList<>();
+		}
+		return result.get();
+	}
+	
+	private List<T> getAllFromDb() {
+		DbTable dbTable = getDbTableAnnotation();
+		// Requete sql
+		String sql = "Select * From " + dbTable.name();
+		Optional<List<T>> result = Database.query(sql, rs -> {
+			try {
+				List<T> list = new ArrayList<>();
+				while(rs.next()) {
+					T obj = (T) dbTable.entity().getConstructor().newInstance();
+					for(Field field : dbTable.entity().getFields()) {
+						if(!field.isAnnotationPresent(DbField.class)) {
+							continue;
+						}
+						obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
+					}
+					list.add(obj);
+				}
+				return list;
+			} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
+				throw new IllegalStateException("Unable to map value to the entity");
+			}
+		});
+		// Return
+		if(result.isEmpty()) {
+			return new ArrayList<>();
+		}
+		return result.get();
+	}
+	
 	private void insert(T obj) {
-		
+		DbTable dbTable = getDbTableAnnotation();
+		// Requete SQL
+		StringBuilder sql = new StringBuilder();
+		StringBuilder values = new StringBuilder();
+		String dbIdName = null; // Nom de l'id en base
+		String attrIdName = null; // Nom de l'id dans la class
+		List<Object> params = new ArrayList<>();
+		sql.append("Insert Into " + dbTable.name() + "(");
+		boolean first = true;
+		try {
+			for(Field field : obj.getClass().getFields()) {
+				if (!field.isAnnotationPresent(DbField.class)) {
+					continue;
+				}
+				// Cherche l'id
+				if (dbIdName == null && field.isAnnotationPresent(DbId.class)) {
+					dbIdName = field.getAnnotation(DbField.class).name();
+					attrIdName = field.getName();
+					continue;
+				}
+				// Recupere la valeur des autres attributs
+				if (!first) {
+					sql.append(",");
+					values.append(",");
+				}
+				sql.append(field.getAnnotation(DbField.class).name());
+				values.append("?");
+				params.add(field.get(obj));
+				first = false;
+			}
+		} catch (IllegalArgumentException | IllegalAccessException e) {
+			throw new IllegalStateException("Unable to access to the attribute", e);
+		}	
+		sql.append(") Values (");
+		sql.append(values);
+		sql.append(")");
+		// Verif que l'on a bien le nom de l'id
+		if(dbIdName == null) {
+			throw new IllegalStateException("Unable to find id field");
+		}
+		// Execution de la requete
+		Map<String, Object> newId = Database.insert(sql.toString(), params, new String[]{dbIdName});
+		if (newId.isEmpty()) {
+			throw new IllegalStateException("Unable to save data");
+		}
+		// Application nouvelle id
+		Object val = newId.get(dbIdName);
+		try {
+			if (val instanceof BigDecimal) {
+				BigDecimal b = (BigDecimal) val;
+				obj.getClass().getField(attrIdName).set(obj, b.longValue());
+			} else {
+				obj.getClass().getField(attrIdName).set(obj, val);
+			}
+		} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
+			throw new IllegalStateException("Unable to set id", e);
+		}
 	}
 	
 	private void update(T obj) {
-		
+		DbTable dbTable = getDbTableAnnotation();
+		// Requete SQL
+		StringBuilder sql = new StringBuilder();
+		StringBuilder where = new StringBuilder();
+		List<Object> params = new ArrayList<>();
+		sql.append("Update " + dbTable.name() + " Set ");
+		where.append(" Where ");
+		boolean first = true;
+		for (Field field : obj.getClass().getFields()) {
+			try {
+				if (!field.isAnnotationPresent(DbField.class)) {
+					continue;
+				}
+				// Si c'est l'id
+				if (field.isAnnotationPresent(DbId.class)) {
+					where.append(field.getAnnotation(DbField.class).name() + " = ?");
+					continue;
+				}
+				// Sinon ajoute dans le set
+				if (!first) {
+					sql.append(",");
+				}
+				sql.append(field.getAnnotation(DbField.class).name() + " = ?");
+				params.add(field.get(obj));
+				first = false;
+			} catch (IllegalArgumentException | IllegalAccessException e) {
+				throw new IllegalStateException("Unable to access to the attribute", e);
+			}
+		}
+		sql.append(where);
+		params.add(obj.getId());
+		// Execution requete
+		if(!Database.execute(sql.toString(), params)) {
+			throw new IllegalStateException("Unable to save data");
+		}
 	}
 
 }

+ 13 - 0
src/db/table/EspaceTable.java

@@ -6,5 +6,18 @@ import entity.Espace;
 
 @DbTable(name = "Espace", entity = Espace.class)
 public class EspaceTable extends Table<Espace>{
+	
+	private static EspaceTable instance;
+	
+	private EspaceTable() {
+		// Private constructor for singleton
+	}
+	
+	public static EspaceTable getInstance() {
+		if(instance == null) {
+			instance = new EspaceTable();
+		}
+		return instance;
+	}
 
 }

+ 12 - 2
src/servlets/TestDb.java

@@ -2,6 +2,7 @@ package servlets;
 
 import java.io.IOException;
 import java.sql.ResultSet;
+import java.util.List;
 import java.util.Optional;
 
 import javax.servlet.ServletException;
@@ -13,6 +14,7 @@ import javax.servlet.http.HttpServletResponse;
 import db.Database;
 import db.ManageTable;
 import db.table.EspaceTable;
+import entity.Espace;
 
 /**
  * Servlet implementation class TestDb
@@ -33,8 +35,16 @@ public class TestDb extends HttpServlet {
 	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 	 */
 	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-		EspaceTable et = new EspaceTable();
-		et.findById(1);
+		EspaceTable et = EspaceTable.getInstance();
+		List<Espace> e = et.getAll();
+		System.out.println(e.size());
+		e.forEach(elt -> System.out.println(elt.id + " " + elt.libelle));
+		Espace ee = et.getById(1);
+		ee.libelle = "Hello";
+		et.save(ee);
+		e = et.getAll();
+		System.out.println(e.size());
+		e.forEach(elt -> System.out.println(elt.id + " " + elt.libelle));
 		response.getWriter().append("Served at: ").append(request.getContextPath());
 	}