2017-09-18 3 views
1

Je travaille sur un projet Spring MVC où j'ai besoin d'obtenir les tables et les attributs d'une base de données Postgres sélectionnée et de les stocker dans un tableau dès le chargement de la page.Récupérer les colonnes et les tables d'une base de données dans Postgres

J'ai actuellement écrit l'appel ajax suivant à travers lequel je suis capable de récupérer les tables et d'afficher sous la base de données respective.

pic 1

VisualEditor.js

drop: function (e, ui) { 

    var mouseTop = e.clientY; 
    var mouseLeft = e.clientX; 

    var dropElem = ui.draggable.attr('class'); 
    droppedElement = ui.helper.clone(); 
    ui.helper.remove(); 
    $(droppedElement).removeAttr("class"); 
    $(droppedElement).draggable({containment: "container"}); 
    jsPlumb.repaint(ui.helper); 


    //If the dropped Element is a TABLE then-> 
    if (dropElem == "stream ui-draggable ui-draggable-handle") { 
     var newAgent = $('<div>'); 
     jsPlumb.addEndpoint(newAgent,connectorProperties); 
     newAgent.attr('id', i).addClass('streamdrop'); 
     var elemType = "table"; 
     $("#container").addClass("disabledbutton"); 
     $("#toolbox").addClass("disabledbutton"); 

     $('#container').append(newAgent); 

     $.ajax({ 
      type: "post", 
      url: "http://localhost:8080/controllers/tables", 
      cache: false, 
      success: function(response){ 
       if (response !== "{}"){ 

       var array = response.replace("{", "").replace("}", ""); 
       var index = array.indexOf("[") +1; 
       var stringval = array.split(":"); 
       var stringval2 = array.substring(index,array.indexOf("]")).split(","); 
       var db_names = new Array(); 
       var table_names = new Array(); 
       var column_names = new Array(); 

       for(var i = 0 ;i < stringval.length-1 ;i++) 
       { 
        db_names[i] = eval(stringval[i]); 
        if(db_names[i]=="testdb"){ 
         var StreamArray = new Array(); 
        } 
        var listId = "db"+i; 
        var dropdownId ="mydrpdown"+i; 
        table_names[i] = new Array(); 
        $("#lot").append(
         "<li onclick='myFunction(\""+dropdownId+"\","+i+","+stringval2.length+")' class='list-group-item dropbtn' id='"+listId+"'> " + db_names[i] + 
         "</li> "+ 
         "<div id='" + dropdownId +"' class='dropdown-content'> " + 
         "<a onclick='setDatabase(\""+db_names[i]+"\",\""+listId+"\")'> Make This as Default Database</a>"+ 
         "</div>" 
        ); 
        $("#databaseID").append(
         "<option>" + db_names[i] +"</option>" 
        ); 

        for(var j=0;j < stringval2.length;j++) 
        { 
         /** 
         * Loading the Predefined Databases and Tables of the Connected DB 
         */ 
         var table_id= "tableId"+i+j; 
         if(eval(stringval2[j]) != null){ 

         table_names[i][j] = eval(stringval2[j]); 

         if(db_names[i]=="testdb") 
         { 
          StreamArray[j] = new Array(4); 
          StreamArray[j][0] = table_names[i][j]; 

          /** 
          * table_names array values at the moment are: 
          * customer,department and students 
          * So the following ajax call should pass each table name to the listTables 
          * method in the controller and fetch the respective columns of each table 
          */ 

          $.ajax({ 
           type: "post", 
           url: "http://localhost:8080/controllers/listTables/{tablename}", 
           data: { tablename: table_names[i][j]} , 
           cache: false, 
           success: function(response){ 
            if (response !== "{}"){ 

           var array = response.replace("{", "").replace("}", ""); 
           var index = array.indexOf("[") +1; 
           var stringval = array.split(":"); 
           var stringval2 = array.substring(index,array.indexOf("]")).split(","); 
           var db_names = new Array(); 
           var table_names = new Array(); 
           var column_names = new Array(); 

           for(var i = 0 ;i < stringval.length-1 ;i++){ 

           } 
            } 
           } 
          }); 

         } 

          $("#lot").append(
          "<li class='list-group-item'style = 'display:none' id='"+table_id+"'> "+table_names[i][j]+" </li>"); 
        } 
       } 

       $("#lot").append(
        "</br>"); 

       array = array.slice(array.indexOf("]") +2); 

       index = array.indexOf("[") +1; 
       stringval2 = array.substring(index,array.indexOf("]")).split(","); 
       } 
      } 
     }, 
     error: function(xhr, status, error){ 

       alert("Error while loading the query"); 
     } 
    }); 

     $("property").show(); 
     $(".toolbox-titlex").show(); 
     $(".panel").show(); 

J'ai écrit 2 appels ajax incorporés dans les noms_tables pour obtenir dans le premier rendez-vous et les column_names suivants. Mais je devine que ce n'est pas un moyen très efficace. Mais je ne suis pas sûr de savoir comment obtenir les deux en même temps.

EditorController.java

@RequestMapping(value= "/tables", method = RequestMethod.POST) 
public @ResponseBody 
String tables(HttpServletRequest request, HttpServletResponse response) 
throws Exception { 

    Map<String, List<String>> alvalues = new HashMap<String, List<String>>();; 
    String queryString = request.getParameter("query"); 
// ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Module.xml"); 

    //CustomerDao customerDAO = (CustomerDao) context.getBean("CustomerDao"); 
    alvalues = customerDAO.getAllTables(); 
    Gson gson = new Gson(); 
    String element = gson.toJson(alvalues); 
     System.out.println(element); 

      return element; 


} 

@RequestMapping(value= "/listTables/{tablename}", method = RequestMethod.POST) 
public @ResponseBody 
String listTables(HttpServletRequest request, HttpServletResponse response,@PathVariable("tablename") String tablename) 
throws Exception { 

    Map<String, List<String>> alvalues = new HashMap<String, List<String>>();; 
    String queryString = request.getParameter("query"); 

    alvalues = customerDAO.getAllFields(tablename); 
    Gson gson = new Gson(); 
    String element = gson.toJson(alvalues); 
     System.out.println(element); 

      return element; 


} 

CustomerDAO.java

public Map<String, List<String>> getAllTables(); 
public Map<String, List<String>> getAllFields(String tablename); 

jdbcCustomerDAO.java

public Map<String, List<String>> getAllTables(){ 


     int k = 1; 
     Map<String, List<String>> map = new HashMap<String, List<String>>(); 
     ArrayList<String> databases = getAllDatabse(); 


     String sql = "SELECT table_name FROM information_schema.tables WHERE table_schema='public'"; 

     Connection conn = null; 

     for(int i=0;i<=databases.size();i++) 
     { 
     try { 
      Class.forName("org.postgresql.Driver"); 
      conn = DriverManager.getConnection(
       "jdbc:postgresql://localhost:5432/"+databases.get(i),"postgres", "123"); 

      PreparedStatement ps = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE, 
        ResultSet.CONCUR_UPDATABLE); 


      ResultSet rs = ps.executeQuery(); 
      ArrayList<String> alvalues = new ArrayList<String>(); 
       while(rs.next()){ 
        alvalues.add(rs.getString(1)); 

       } 

       map.put(databases.get(i), alvalues); 
       rs.beforeFirst(); 



      for (Map.Entry<String, List<String>> entry : map.entrySet()) { 

       String key = entry.getKey(); 

       List<String> values = entry.getValue(); 

       System.out.println("Key = " + key); 

       System.out.println("Values = " + values + "n"); 

      } 
      conn.close(); 

    } 
     catch(Exception e){ 

      System.out.println(e.getMessage()); 
     } 
     } 
     return map; 
    } 


public Map<String, List<String>> getAllFields(String tablename){ 


     int k = 1; 
     Map<String, List<String>> map = new HashMap<String, List<String>>(); 
     ArrayList<String> databases = getAllDatabse(); 


     String sql = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '"+tablename+"'"; 

     Connection conn = null; 

     for(int i=0;i<=databases.size();i++) 
     { 
     try { 
      Class.forName("org.postgresql.Driver"); 
      conn = DriverManager.getConnection(
       "jdbc:postgresql://localhost:5432/"+databases.get(i),"postgres", "123"); 

      PreparedStatement ps = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE, 
       ResultSet.CONCUR_UPDATABLE); 


      ResultSet rs = ps.executeQuery(); 
      ArrayList<String> alvalues = new ArrayList<String>(); 
       while(rs.next()){ 
        alvalues.add(rs.getString(1)); 

       } 

       map.put(databases.get(i), alvalues); 
       rs.beforeFirst(); 



      for (Map.Entry<String, List<String>> entry : map.entrySet()) { 

       String key = entry.getKey(); 

       List<String> values = entry.getValue(); 

       System.out.println("Key = " + key); 

       System.out.println("Values = " + values + "n"); 

      } 
      conn.close(); 

    } 
     catch(Exception e){ 

      System.out.println(e.getMessage()); 
     } 
     } 
     return map; 
    } 

Mais je ne suis pas en mesure d'obtenir les noms de colonnes avec succès.

Console Log

Selon cette étude, les noms_tables sont récupérées avec succès, mais les noms de colonnes sont vides.

INFO : com.postgres.controllers.HomeController - Welcome home! The client locale is en_US. 
postgres 
postgreside 
testdb 
Key = postgres 
Values = []n 
Key = postgreside 
Values = [constraints, users, notes, session, projects, databases, tables, columns, index, checksconstraint, additionalproperties, foreignref, primaryref, referenceproperties, department, person]n 
Key = postgres 
Values = []n 
Key = testdb 
Values = [customer, department, students]n 
Key = postgreside 
Values = [constraints, users, notes, session, projects, databases, tables, columns, index, checksconstraint, additionalproperties, foreignref, primaryref, referenceproperties, department, person]n 
Key = postgres 
Values = []n 
Index: 3, Size: 3 
{"testdb":["customer","department","students"],"postgreside":["constraints","users","notes","session","projects","databases","tables","columns","index","checksconstraint","additionalproperties","foreignref","primaryref","referenceproperties","department","person"],"postgres":[]} 
postgres 
postgreside 
testdb 
postgres 
postgreside 
testdb 
postgres 
postgreside 
testdb 
Key = postgres 
Values = []n 
Key = postgres 
Values = []n 
Key = postgres 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Key = testdb 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Index: 3, Size: 3 
{"testdb":[],"postgreside":[],"postgres":[]} 
Key = testdb 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Index: 3, Size: 3 
{"testdb":[],"postgreside":[],"postgres":[]} 
Key = testdb 
Values = []n 
Key = postgreside 
Values = []n 
Key = postgres 
Values = []n 
Index: 3, Size: 3 
{"testdb":[],"postgreside":[],"postgres":[]} 

Je voudrais avoir une seule méthode pour récupérer les noms de table et leurs attributs/colonnes et le stocker dans le StreamArray pour que je ne ai pas besoin pour accéder à la chaque fois que DB je besoin de se référer à les données connexes.

Toutes les suggestions sur la façon dont je pourrais obtenir les noms des colonnes et les stocker dans le StreamArray que j'ai créé sous le VisualEditor.js seront très appréciées.

+0

Votre requête pour la table "columns" manque une condition where pour le schéma: vous pouvez avoir le même nom de table dans différents schémas. –

Répondre

0

Dans le cas général, vous pouvez gérer plus d'une base de données, plusieurs schémas et chaque nom de table peut apparaître dans plusieurs schémas. Dans votre cas, il peut y avoir plus de schémas que vous devez exclure. Ou vous pouvez décider que seul le schéma «public» est pertinent. (Soyez prudent avec les décisions de ce type.)

select table_catalog, table_schema, table_name, column_name 
from information_schema.columns 
where table_catalog = 'your_db_name' 
    and table_schema <> 'information_schema' 
    and table_schema <> 'pg_catalog' 
order by table_catalog, table_schema, table_name, column_name; 
+0

Vous ne verrez que les tables et les colonnes de votre base de données actuelle (table_catalog), pas des autres: –

+0

'select distinct (table_catalog) from information_schema.columns' –