Cache et SQLite
Cet article est la suite de l’article Client Java JWT
Dans cet article nous allons voir comment implémenter la librairie SQLite pour modifier notre précédente application Java et y ajouter la gestion d’un cache local dans une base de données SQLite.
Dans un premier temps, implémentons l’objet ThreadRefreshCache héritant logiquement de Thread. Cette classe va nous permettre de :
-stocker les requêtes effectuées sur le logiciel pendant la période d’hors-ligne dans un cache
-envoyer toutes les modifications faites en local au serveur dès que la connexion est rétablie
-recevoir par la suite les données actualisées du serveur pour les stocker par la suite dans les BDs en local.
Voici le contenu de notre objet :
public class ThreadRefreshCache extends Thread implements PropertyChangeListener{
private String DB_INSERT = "INSERT INTO product(id, name, type, price) VALUES(?,?,?,?)";
private String DB_UPDATE = "UPDATE product SET name=?, type=?, price=? WHERE id=?";
private String DB_UPDATE_ID = "UPDATE product SET id=? WHERE id=?";
private String DB_DELETE = "DELETE FROM product WHERE id=?";
private String CACHE_DELETE = "DELETE FROM cache WHERE id=?";
private String CACHE_SELECT_ACTION = "SELECT * FROM cache WHERE action=?";
private DBHelper dbHelper;
private PropertyChangeSupport ptChSupport = new PropertyChangeSupport(this);
private ConnectionRest connectionRest = null;
private ArrayList<Cache> listCachePost = new ArrayList<Cache>();
private ArrayList<Cache> listCachePut = new ArrayList<Cache>();
private ArrayList<Cache> listCacheDelete = new ArrayList<Cache>();
private ArrayList<Product> listProductPost = new ArrayList<Product>();
private ArrayList<Product> listProductPut = new ArrayList<Product>();
private int cptPost, cptPut, cptDelete;
public ThreadRefreshCache() {
super();
dbHelper = new DBHelper();
}
@Override
public void run(){
refreshCache();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getSource().equals(connectionRest)){
connectionRest.removePropertyChangeListener(this);
if(evt.getPropertyName().equals("POST")){
String newID = (String)evt.getNewValue();
if(!newID.equals("")&&newID.charAt(0)!='{'){
refreshCachePostFin(Integer.parseInt(newID.trim()));
}
}else if(evt.getPropertyName().equals("PUT")){
String retour = (String)evt.getNewValue();
if(retour.equals("")||retour.charAt(0)!='{'){
refreshCachePutFin();
}
}else if(evt.getPropertyName().equals("DELETE")){
String retour = (String)evt.getNewValue();
if(retour.equals("")||retour.charAt(0)!='{'){
refreshCacheDeleteFin();
}
}else if(evt.getPropertyName().equals("GET")){
refreshCacheGetFin(parse((String)evt.getNewValue()));
ptChSupport.firePropertyChange("refreshCache", null, null);
}
}
}
private void refreshCache() {
listProductPost.clear();
listProductPut.clear();
listCachePost.clear();
listCachePut.clear();
listCacheDelete.clear();
cptPost = 0;
cptPut = 0;
cptDelete = 0;
// Creation des listes : listCachePost, listCachePut et listCacheDelete
listCachePost = selectFromAction(1);//POST
listCachePut = selectFromAction(2);//PUT
listCacheDelete = selectFromAction(3);//DELETE
debugCache();//TODO
//Optimisation if POST PUT DELETE
for (int i = 0; i < listCachePost.size(); i++) {
for (int j = 0; j < listCacheDelete.size(); j++) {
boolean find = false;
for (int k = 0; k < listCachePut.size(); k++) {
if (listCachePost.get(i).getIdObj() == listCachePut.get(k).getIdObj() && listCachePut.get(k).getIdObj() == listCacheDelete.get(j).getIdObj()) {
delCache(listCachePut.get(k).getId());
listCachePut.remove(k);
k--;
find = true;
}
}
if (find) {
delCache(listCachePost.get(i).getId());
listCachePost.remove(i);
i--;
delCache(listCacheDelete.get(j).getId());
listCacheDelete.remove(j);
j--;
}
}
}
//Optimisation if POST DELETE
for (int i = 0; i < listCachePost.size(); i++) {
for (int j = 0; j < listCacheDelete.size(); j++) {
if (listCachePost.get(i).getIdObj() == listCacheDelete.get(j).getIdObj()) {
delCache(listCachePost.get(i).getId());
listCachePost.remove(i);
i--;
delCache(listCacheDelete.get(j).getId());
listCacheDelete.remove(j);
j = listCacheDelete.size();
}
}
}
//Optimisation if POST PUT
for (int i = 0; i < listCachePost.size(); i++) {
for (int j = 0; j < listCachePut.size(); j++) {
if (listCachePost.get(i).getIdObj() == listCachePut.get(j).getIdObj()) {
delCache(listCachePut.get(j).getId());
listCachePut.remove(j);
j--;
}
}
}
//Optimisation if DELETE PUT
for (int i = 0; i < listCacheDelete.size(); i++) {
boolean find = false;
for (int j = 0; j < listCachePut.size(); j++) {
if (listCacheDelete.get(i).getIdObj() == listCachePut.get(j).getIdObj()) {
delCache(listCachePut.get(j).getId());
listCachePut.remove(j);
j--;
find = true;
}
}
if (find) {
delCache(listCacheDelete.get(i).getId());
listCacheDelete.remove(i);
i--;
}
}
//3- Creation des listes : listProductPost, listProductPut
listProductPost = getListFromCache(listCachePost);
listProductPut = getListFromCache(listCachePut);
debugCache();//TODO
refreshCachePostDebut();
}
private void refreshCachePostDebut() {
if((listProductPost.size() == 0) || (listProductPost.size() == cptPost)) {
refreshCachePutDebut();
}else{
connectionRest = new ConnectionRest("POST");
connectionRest.setObj(dbHelper.convertToJSONObject(listProductPost.get(cptPost)));
connectionRest.addPropertyChangeListener(this);
connectionRest.start();
}
}
private void refreshCachePostFin(int newId) {
try {
//MAJ l'id
Connection connection = dbHelper.getConnection();
PreparedStatement pstmt = null;
if(newId != listCachePost.get(cptPost).getIdObj()) {
pstmt = connection.prepareStatement(DB_UPDATE_ID);
pstmt.setInt(1, newId);
pstmt.setInt(2, listCachePost.get(cptPost).getIdObj());
pstmt.executeUpdate();
pstmt.close();
}
delCache(listCachePost.get(cptPost).getId());
cptPost++;
} catch (SQLException e) {
e.printStackTrace();
}
refreshCachePostDebut();
}
private void refreshCachePutDebut() {
if((listProductPut.size() == 0) || (listProductPut.size() == cptPut)) {
refreshCacheDeleteDebut();
}else{
connectionRest = new ConnectionRest("PUT");
connectionRest.setObj(dbHelper.convertToJSONObjectID(listProductPut.get(cptPut)));
connectionRest.addPropertyChangeListener(this);
connectionRest.start();
}
}
private void refreshCachePutFin() {
delCache(listCachePut.get(cptPut).getId());
cptPut++;
refreshCachePutDebut();
}
private void refreshCacheDeleteDebut() {
if((listCacheDelete.size() == 0) || (listCacheDelete.size() == cptDelete)) {
refreshCacheGetDebut();
}else{
try {
connectionRest = new ConnectionRest("DELETE");
JSONObject jsonProduct = new JSONObject();
jsonProduct.put("id", listCacheDelete.get(cptDelete).getIdObj());
connectionRest.setObj(jsonProduct);
connectionRest.addPropertyChangeListener(this);
connectionRest.start();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void refreshCacheDeleteFin() {
delCache(listCacheDelete.get(cptDelete).getId());
cptDelete++;
refreshCacheDeleteDebut();
}
private void refreshCacheGetDebut() {
connectionRest = new ConnectionRest("GET");
connectionRest.addPropertyChangeListener(this);
connectionRest.start();
}
private void refreshCacheGetFin(ArrayList<Product> listPdt) {
if(listPdt != null && listPdt.size() > 0) {
ArrayList<Product> listPdtPost = new ArrayList<Product>();
ArrayList<Product> listPdtPut = getListFromDb(listPdt);
//Création de la liste des produits a créer
for(int i = 0; i < listPdt.size(); i++) {
boolean idEstDanslistPut = false;
for(int k = 0; k < listPdtPut.size(); k++) {
if(listPdtPut.get(k).getId()==listPdt.get(i).getId()) {
idEstDanslistPut = true;
k = listPdtPut.size();
}
}
if(!idEstDanslistPut) {
listPdtPost.add(listPdt.get(i));
}
}
//Création des produits
try {
Connection connection = dbHelper.getConnection();
for(int i = 0; i < listPdtPost.size(); i++) {
PreparedStatement pstmt = connection.prepareStatement(DB_INSERT);
pstmt.setInt(1, listPdtPost.get(i).getId());
pstmt.setString(2, listPdtPost.get(i).getName());
pstmt.setString(3, listPdtPost.get(i).getType());
pstmt.setDouble(4, listPdtPost.get(i).getPrice());
pstmt.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
//Mise à jour des produits
try {
Connection connection = dbHelper.getConnection();
for(int i = 0; i < listPdtPut.size(); i++) {
PreparedStatement pstmt = connection.prepareStatement(DB_UPDATE);
pstmt.setString(1, listPdtPut.get(i).getName());
pstmt.setString(2, listPdtPut.get(i).getType());
pstmt.setDouble(3, listPdtPut.get(i).getPrice());
pstmt.setInt(4, listPdtPut.get(i).getId());
pstmt.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void delCache(int id) {
try {
Connection conn = dbHelper.getConnection();
PreparedStatement pstmt = conn.prepareStatement(CACHE_DELETE);
pstmt.setInt(1, id);
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private ArrayList<Cache> selectFromAction(int action) {
ArrayList<Cache> listResult = new ArrayList<Cache>();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Connection conn = dbHelper.getConnection();
pstmt = conn.prepareStatement(CACHE_SELECT_ACTION);
pstmt.setInt(1, action);
rs = pstmt.executeQuery();
while (rs.next()) {
listResult.add(new Cache(rs));
}
rs.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
return listResult;
}
private ArrayList<Product> getListFromCache(ArrayList<Cache> listCache) {
//Recherche des id déjà dans la base de données local
String listIdApi = "";
for(int i = 0; i < listCache.size(); i++) {
String strSeparateur = ",";
if (i == 0) {
strSeparateur = "";
}
listIdApi += strSeparateur + listCache.get(i).getIdObj();
}
return getListIn(listIdApi);
}
private ArrayList<Product> getListFromDb(ArrayList<Product> listProduct) {
//Recherche des id déjà dans la base de données local
String listIdApi = "";
for(int i = 0; i < listProduct.size(); i++) {
String strSeparateur = ",";
if (i == 0) {
strSeparateur = "";
}
listIdApi += strSeparateur + listProduct.get(i).getId();
}
return getListIn(listIdApi);
}
private ArrayList<Product> getListIn(String listIdApi) {
ArrayList<Product> listResult = new ArrayList<Product>();
try {
Connection connection = dbHelper.getConnection();
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM product WHERE id IN ("+listIdApi+")");
while (rs.next()) {
listResult.add(new Product(rs));
}
} catch (SQLException e1) {
e1.printStackTrace();
}
return listResult;
}
private ArrayList<Product> parse(String json) {
try {
if(!json.equals("")&&json.charAt(0)!='{') {
ArrayList<Product> listPdt = new ArrayList<Product>();
final JSONArray jProductArray = new JSONArray(json);
int debut = 0;
//Gestion del
if((jProductArray.length()>0)&&(jProductArray.optJSONObject(0).isNull("DEL")!=true)) {
debut++;
JSONObject objJSON = jProductArray.optJSONObject(0);
String strDEL = objJSON.getString("DEL");
String listDEL[]= strDEL.split(",");
int idListDEL[] = new int[listDEL.length];
for(int k = 0 ; k < listDEL.length ; k++) {
idListDEL[k]= Integer.parseInt(listDEL[k]);
dbHelper = new DBHelper();
Connection conn = dbHelper.getConnection();
PreparedStatement pstmt;
try {
pstmt = conn.prepareStatement(DB_DELETE);
pstmt.setInt(1, idListDEL[k]);
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//Chargement des donnees
for (int i = debut; i < jProductArray.length(); i++) {
listPdt.add(new Product(jProductArray.optJSONObject(i)));
}
return listPdt;
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
private void debugCache() { //TODO
Iterator<Cache> itrCachePost = listCachePost.iterator();
Iterator<Cache> itrCachePut = listCachePut.iterator();
Iterator<Cache> itrCacheDelete = listCacheDelete.iterator();
System.err.println("\nCachePost: ");
while (itrCachePost.hasNext()) {
Cache cache = itrCachePost.next();
System.err.println(""+cache);
}
System.err.println("\nCachePut: ");
while (itrCachePut.hasNext()) {
Cache cache = itrCachePut.next();
System.err.println(""+cache);
}
System.err.println("\nCacheDelete: ");
while (itrCacheDelete.hasNext()) {
Cache cache = itrCacheDelete.next();
System.err.println(""+cache);
}
}
public void addPropertyChangeListener(PropertyChangeListener l){ptChSupport.addPropertyChangeListener(l);}
public void removePropertyChangeListener(PropertyChangeListener l){ptChSupport.removePropertyChangeListener(l);}
}
Explication rapide des fonctions principales :
–refreshCache() est appelée lors du run avec un .start(). Les ArrayList de type Cache stockent les requêtes effectuées hors ligne après » l’optimisation » (le fait d’éviter tout stockage supplémentaire et inutile de requête en fonction de leur enchaînement).
Exemple : Si un document est modifié puis supprimé, il n’est pas nécessaire de communiquer ces 2 étapes au serveur, seulement sa suppression. Ainsi, le serveur n’aura plus qu’à faire une seule opération pour mettre à jour sa BD.
Enfin, les BDs modifiées en local à chaque itération/nouvelle requête sont stockées dans des ArrayList de type Product.
-Enchaînement des fonctions refreshDebut() et Fin() :
Dans chaque fonction « debut », les requêtes de type POST, PUT, DELETE ou GET sont envoyées sous format JSON au serveur. On supprime alors du cache la requête qui vient d’être envoyée dans les fonctions « fin ». Ces dernières sont notifiées de l’envoi des requêtes grâce à l’implémentation d’un PropertyChange de la classe PropertyChangeListener.
Dans le cas particulier de refreshCachePostDebut(), on met à jour l’id de la requête concernée.
Enfin, dans refreshCacheGetFin, on stocke en local la BD du serveur qui vient d’être modifiée par nos requêtes (et éventuellement par d’autres utilisateurs depuis notre passage hors-ligne).
La classe RestJFrame doit être modifiée pour pouvoir utiliser ThreadRefreshCache() :
@Override
public void actionPerformed(ActionEvent e) {
...
if (e.getSource().equals(boutonRefresh)) {
threadRefreshCache = new ThreadRefreshCache();
threadRefreshCache.addPropertyChangeListener(this);
threadRefreshCache.start();
refreshJDialog.refresh();
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
...
else if (evt.getSource().equals(threadRefreshCache)&&evt.getPropertyName().equals("refreshCache")){
if(refreshJDialog.isOpen()) {
refreshJDialog.close();
}
threadRefreshCache.removePropertyChangeListener(this);
refresh()
}
}
La classe RefreshJDialog instanciée au-dessus est une classe qui permet de gérer la fenêtre affichant que la synchronisation des données a bien eu lieu.
public RefreshJDialog(JFrame mainFrame){
super(mainFrame);
initialize();
}
public void refresh(){
open = true;
this.setLocationRelativeTo(getParent());
this.setVisible(true);
}
public void close(){
open = false;
this.dispose();
}
private void initialize() {
this.setSize(240, 150);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.setTitle("Synchronisation des données");
refreshLabel = new JLabel("Synchronisation des données...");
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
getContentPane().add(refreshLabel, gbc);
}
public boolean isOpen() {return open;}
}
Voici les objets Product et Cache qui permettent de stocker les requêtes et les BDs en local.
public class Product {
private int id;
private String name;
private String type;
private double price;
public Product() {
id = -1;
name = "Nom";
type = "Type";
price = 1.0;
}
public Product(ResultSet rs) throws SQLException {
id = rs.getInt("id");
name = rs.getString("name");
type = rs.getString("type");
price = rs.getDouble("price");
}
public Product(JSONObject jObject) {
id = jObject.optInt("id");
name = jObject.optString("name");
type = jObject.optString("type");
price = jObject.optDouble("price");
}
public Object elementAt(int pNumColonne){
switch (pNumColonne) {
case 0:
return getId();
case 1:
return getName();
case 2:
return getType();
case 3:
return getPrice();
default:
return null;
}
}
public int getId() { return id; }
public String getName() { return name; }
public String getType() { return type; }
public double getPrice() { return price; }
public void setId(int pId) { id=pId; }
public void setName(String pName) { name=pName; }
public void setType(String pType) { type=pType; }
public void setPrice(double pPrice) { price=pPrice; }
@Override
public String toString() {
return id+" "+name+" "+type+" +price";
}
}
public class Cache {
private int id, idObj, action;
private String obj;
public Cache(int pId) {
id = pId;
idObj = -1;
obj = "objet";
action = 1;
}
public Cache(JSONObject jObject) {
id = jObject.optInt("id");
idObj = jObject.optInt("id_obj");
obj = jObject.optString("obj");
action = jObject.optInt("action");
}
public Cache(ResultSet rs) throws SQLException {
id = rs.getInt("id");
idObj = rs.getInt("id_obj");
obj = rs.getString("obj");
action = rs.getInt("action");
}
public Object elementAt(int pNumColonne){
switch (pNumColonne) {
case 0:
return getId();
case 1:
return getIdObj();
case 2:
return getObj();
case 3:
return getAction();
default:
return null;
}
}
public int getId() { return id; }
public int getIdObj() { return idObj; }
public String getObj() { return obj; }
public int getAction() { return action; }
public void setIdObj(int idObj) { this.idObj = idObj; }
public void setObj(String obj) { this.obj = obj; }
public void setAction(int action) { this.action = action; }
@Override
public String toString() {
return id+" "+idObj+" "+action;
}
}
La classe ProductTableModel change intégralement car elle n’implémente plus de PropertyChangeListener et qu’on doit y effectuer la gestion du cache dans la majorité des fonctions.
Toutefois, son rôle reste le même.
public class ProductTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private String DB_SELECT = "SELECT id, name, type, price FROM product";
private String DB_INSERT = "INSERT INTO product(name, type, price) VALUES(?,?,?)";
private String DB_UPDATE = "UPDATE product SET name=?, type=?, price=? WHERE id=?";
private String DB_DELETE = "DELETE FROM product WHERE id = ?";
private String CACHE_INSERT = "INSERT INTO cache(id_obj, obj, action) VALUES(?,?,?)";
private DBHelper dbHelper = null;
private String[] columnNames = {"Id", "Nom", "Type", "Prix"};
private ArrayList listProducts = new ArrayList();
public ProductTableModel(){
super();
dbHelper = new DBHelper();
}
public void addLine(){
Connection conn = dbHelper.getConnection();
Product product = new Product();
try {
PreparedStatement pstmt = conn.prepareStatement(DB_INSERT);
pstmt.setString(1, product.getName());
pstmt.setString(2, product.getType());
pstmt.setDouble(3, product.getPrice());
pstmt.executeUpdate();
pstmt.close();
product.setId(dbHelper.getLastId());
} catch (SQLException e) {
e.printStackTrace();
}
listProducts.add(product);
//Gestion Cache
try {
PreparedStatement pstmt = conn.prepareStatement(CACHE_INSERT);
pstmt.setInt(1, product.getId());
pstmt.setString(2, "product");
pstmt.setInt(3, 1);//POST
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void refreshProducts() {
try{
Connection conn = dbHelper.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(DB_SELECT);
listProducts.clear();
// Boucle sur le set de résultat
while (rs.next()) {
listProducts.add(new Product(rs));
}
rs.close();
stmt.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
@Override
public void setValueAt(Object value, int row, int column) {
Product product = null;
if(row < listProducts.size()){
product = listProducts.get(row);
switch (column) {
case 1:
product.setName((String) value);
break;
case 2:
product.setType((String) value);
break;
case 3:
product.setPrice((Double) value);
break;
default:
break;
}
Connection conn = dbHelper.getConnection();
try {
PreparedStatement pstmt = conn.prepareStatement(DB_UPDATE);
pstmt.setString(1, product.getName());
pstmt.setString(2, product.getType());
pstmt.setDouble(3, product.getPrice());
pstmt.setInt(4, product.getId());
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
//Gestion Cache
try {
PreparedStatement pstmt = conn.prepareStatement(CACHE_INSERT);
pstmt.setInt(1, product.getId());
pstmt.setString(2, "product");
pstmt.setInt(3, 2);//PUT
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Override
public Class<? extends Object> getColumnClass(int c) {
if(getValueAt(0, c)!=null){
return getValueAt(0, c).getClass();
}else{
return null;
}
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
if (columnNames[column] != null) {
return columnNames[column];
} else {
return "";
}
}
@Override
public int getRowCount() {
if (listProducts!=null)
return listProducts.size();
else
return 0;
}
@Override
public Object getValueAt(int aRow, int aColumn) {
Product obj = null;
if(listProducts!=null && aRow<listProducts.size()){
obj = listProducts.get(aRow);
}
if(obj!= null){
return obj.elementAt(aColumn);
}else{
return null;
}
}
@Override
public boolean isCellEditable(int row, int column) {
if (column != 0){
return true;
}
return false;
}
public Product get(int gRow) {
return listProducts.get(gRow);
}
public void remove(int gRow) {
Connection conn = dbHelper.getConnection();
int id = ((Product)listProducts.get(gRow)).getId();
try {
PreparedStatement pstmt = conn.prepareStatement(DB_DELETE);
pstmt.setInt(1, id);
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
//Gestion Cache
try {
PreparedStatement pstmt = conn.prepareStatement(CACHE_INSERT);
pstmt.setInt(1, id);
pstmt.setString(2, "product");
pstmt.setInt(3, 3);//DELETE
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
listProducts.remove(gRow);
}
}
Voici la classe DBHelper utilisée dans ThreadRefreshCache et ProductTableModel, utilisée principalement pour gérer la création et la modification de base de données :
public class DBHelper {
private final String URL_CONN = "jdbc:sqlite:";
private final String URL_FILE = "product.db";
private static final String CREATE_TB="CREATE TABLE IF NOT EXISTS product(id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT, type TEXT, price REAL);";
private static final String CREATE_CACH="CREATE TABLE IF NOT EXISTS cache(id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "id_obj INTEGER, obj TEXT, action INTEGER);";
private Connection conn = null;
public Connection getConnection() {
if (conn == null) {
try {
File file = new File(URL_FILE);
if(!file.exists()) {
onCreate();
}
conn = DriverManager.getConnection(URL_CONN+URL_FILE);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
return conn;
}
public void onCreate() {
try{
conn = DriverManager.getConnection(URL_CONN+URL_FILE);
createNewDatabase();
createNewTable();
}catch (SQLException e){
e.printStackTrace();
}
}
public JSONObject convertToJSONObject(Product product) {
JSONObject jsonProduct = convertToJSONObjectID(product);
jsonProduct.remove("id");
return jsonProduct;
}
public JSONObject convertToJSONObjectID(Product product) {
JSONObject jsonProduct = new JSONObject();
try {
jsonProduct.put("id", product.getId());
jsonProduct.put("name",product.getName());
jsonProduct.put("type",product.getType());
jsonProduct.put("price", product.getPrice());
} catch (JSONException e) {
e.printStackTrace();
}
return jsonProduct;
}
private void createNewDatabase() throws SQLException {
if (conn != null) {
DatabaseMetaData meta = conn.getMetaData();
System.out.println("The driver name is " + meta.getDriverName());
System.out.println("A new database has been created.");
}
}
private void createNewTable() throws SQLException{
Statement stmt = conn.createStatement();
stmt.execute(CREATE_TB);
stmt.execute(CREATE_CACH);
}
public int getLastId() throws SQLException {
PreparedStatement pstmt = conn.prepareStatement("SELECT MAX(id) newid FROM product");
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
int newId = rs.getInt("newid");
rs.close();
pstmt.close();
return newId;
}
return -1;
}
}
Enfin, l’objet Param est utilisé dans ConnectionRest et LoginJDialog pour obtenir des informations sur le JWT ou le modifier :
public class Param {
private String token;
private static Param param;
private Param() {}
public static Param getIns() {
if(param == null) {
param = new Param();
}
return param;
}
public String getToken() {return token;}
public void setToken(String pToken) {token = pToken;}
}