Java - jTable sort numbers - java

I have searched for very long time so I have decided to write finally here. I have problem with sorting numbers (Integers, doubles, shorts) in a jTable, I have overwritten the getColumnClass method, however it still does not sort numbers correctly.
Here is what I did:
List<Class> types = new ArrayList();
types.add(String.class);
types.add(String.class);
types.add(String.class);
for (int s = 0; s < sloupce.size(); s++) {
try {
Statement st = log.getSt();
ResultSet r = st.executeQuery("SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '" + table + "' AND COLUMN_NAME = '" + sloupce.get(s) + "'");
if (r.next()) {
String typ = r.getString("DATA_TYPE");
if (!typ.equals("varchar")) {
types.add(Integer.class);
} else {
types.add(String.class);
}
}
} catch (Exception e) { System.out.println(e.toString()); }
}
DefaultTableModel tm = new DefaultTableModel(new Object[0][], new String[] {" first column ", " second ", " another "}) {
#Override
public Class getColumnClass(int columnIndex) {
return types.get(columnIndex);
}
};
Then I fill types array withproper classes, when I test the getColumnClass method it really returns proper class (java.lang.Integer), but it still sorts the values incorrectly.
//UPDATE:
I am representing a table from MySQL DB so I have updated my exact code how I am doing it.

Related

Why the place of the option always change?

I'm doing a phone book project in Java, using MySql for school.
I wanted to print the methods using the Class.getDeclaredMethods();
adding them to a Vector of type String.
and invoke a menu() method that prints and accepts the option from the user using Scanner
the problem is that it always changes the methods places.
for example it can print
0.addPerson
1.deleteContact
2.searchByChar
and the next time
0.deleteContact
1.addPerson
2.searchByChar.
the problem is that i have a Switch case depend on it.
the menu function:
public static int menu(Vector<?> options){
System.out.println("The Options: ");
for (int i = 0; i < options.size(); i++) {
System.out.println(i + ". " + options.get(i));
}
Scanner scanner = new Scanner(System.in);
System.out.println("Your Choice: ");
String optionString = scanner.nextLine();
int option = 0;
if(isNumber(optionString)){
option = Integer.valueOf(optionString);
}else{
System.out.println("Please Choose Valid Option");
return menu(options);
}
return option;
}
the methods that get my methods:
public static Vector<String> getClassMethods(Class whichClass){
Method[] methods = whichClass.getDeclaredMethods();
Vector<String> stringMethods = new Vector<>();
for (Method method : methods) {
if(Modifier.toString(method.getModifiers()).equals("protected")){
stringMethods.add(method.getName());
}
}
return stringMethods;
}
my class the connects to the data base:
private boolean getData(Person person){
String sql = "SELECT * FROM " + DB_NAME + " WHERE name = '" + person.getName() + "' and phone_number = '" + person.getPhoneNumber() + "'";
try {
ResultSet resultSet = db.prepareStatement(sql).executeQuery();
if (resultSet.next()) {
return true;
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return false;
}
protected void addPerson(){
Person person = MyUtills.createPerson();
if(getData(person)){
System.out.println(person.getName() + ", " + person.getPhoneNumber() + ": Already in Contacts" );
}else{
add(person);
}
}
private void add(Person person) {
String pName = person.getName();
String pPhone = person.getPhoneNumber();
String pAddress = person.getAddress();
String sql = "INSERT INTO " + DB_NAME + " (name,phone_number,address)" +
"VALUES (?,?,?)";
try {
statement = db.prepareStatement(sql);
statement.setString(1,pName);
statement.setString(2,pPhone);
statement.setString(3,pAddress);
statement.execute();
System.out.println("Added Successfully");
} catch (SQLException e) {
e.printStackTrace();
}
}
//delete contact by name
protected void deleteContact(){
System.out.println("Enter Name Please");
String name = MyUtills.readStringFromUser();
Vector<Person> vector = checkMoreThanOne(name);
if(vector.size() > 1){
System.out.println("Choose One To Delete: ");
int option = menu(vector);
delete(vector.get(option));
}
System.out.println("Deleted");
}
private Vector<Person> checkMoreThanOne(String name) {
Vector<Person> vector = new Vector<>();
String sql = "SELECT * FROM " + DB_NAME;
try {
ResultSet resultSet = db.prepareStatement(sql).executeQuery();
while(resultSet.next()){
String pName = resultSet.getString("name");
String pPhone = resultSet.getString("phone_number");
String pAddress = resultSet.getString("address");
if(pName.equals(name)){
vector.add(new Person(pName,pPhone,pAddress));
}
}
return vector;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//deleting and existing contact;
private void delete(Person person){
String sql = "DELETE FROM " + DB_NAME + " WHERE name = '" + person.getName() + "' and phone_number = '" + person.getPhoneNumber() + "'";
try {
statement = db.prepareStatement(sql);
statement.execute();
System.out.println("Deleted Successfully");
} catch (SQLException e) {
e.printStackTrace();
}
}
//creating a new table for empty data base!
private void createTable() {
try {
statement = db.prepareStatement(SQL_TABLE_STRING);
statement.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
protected void searchByFirstChar(Character character){
Vector<Person> personVector = new Vector<>();
String sql = "SELECT * FROM newphonebook";
try {
ResultSet resultSet = db.prepareStatement(sql).executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
String phoneNum = resultSet.getString("phone_number");
String address = resultSet.getString("address");
if(character.equals(name.charAt(0))){
personVector.add(new Person(name,phoneNum,address));
}
}
System.out.println(personVector);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
public void getOptions(){
Vector<String> options = MyUtills.getClassMethods(DBWriterReader.class);
int option = MyUtills.menu(options);
switch (option){
case 0:
addPerson();
break;
case 1:
deleteContact();
break;
case 2:
// searchByFirstChar();
break;
}
}
}
I know it's not best written but I'm working on it to make it better
The Writing and Reading from the data base works fine, its the way it prints my methods that makes the problem..
If you need to guarantee the order of elements in a data structure, you don't use Vector -- it's not 1999 anymore. Look at the documentation for Vector. You get elements in the order determined by an iterator, not as they are stored.
Change your data structure to an ArrayList, which guarantees order. ArrayLists are also more performant in a single threaded application like yours, because unlike Vector, an ArrayList skips the overhead associated with being synchronized. Using the index of the ArrayList elements may also simplify the way you construct your switch statement.

SQL-Exception in listing

I'm programming a small application in Java, a very basic database containing (fictional) student data. It works quiet okay so far, but I've encountered a problem when trying to make a list containing the curriculum of the university the students are frequenting. I want to list every possible degree, all of which have 6 semesters, along with the courses that can be taken in every category, how many hours per week they take and so on. The first bit works, but I encounter a problem when trying to fill the different categories with their respective courses over each semester. Heres the code (things I deem relevant to the problem are enclosed with two stars):
#Override
public List<List<String>> getStudyingplan(Studies s) throws ApplicationException {
List<List<String>> curriculum= new ArrayList<List<String>>();
ArrayList<String> line = new ArrayList<String>();
ArrayList<String> categories = new ArrayList<String>();
String currentCategory;
String name = s.getName();
String abb= s.getAbbreviation();
String category;
String categoryHeader= ("Mod E C P Cr");
line.add("Course of studies\n" + name + " (" + abb+ ")");
for (int i = 1; i <= 6; i++) {
line.add(i + ". Semester");
}
line.add("");
curriculum.add(line);
line= new ArrayList();
line.add("Category");
for (int i = 1; i <= 6; i++) {
line.add(categoryHeader);
}
line.add("Sum");
curriculum.add(line);
line= new ArrayList();
//Connect to database:
try {
Class.forName(driver).newInstance();
con = DriverManager.getConnection(database);
PreparedStatement giveCategories = con.prepareStatement("SELECT distinct k.* "
+ "FROM CATEGORY c, CURRICULUM cu, MODULE m "
+ "WHERE cu.SABB = ? AND cu.MABB = m.MABB AND m.KABB = c.KABB "
+ "ORDER BY c.INDEX");
**PreparedStatement giveModule = con.prepareStatement("SELECT distinct m.*" +
"FROM MODULE m, STUDIES st, CURRICULUM c" +
"WHERE st.SKABB = ? AND c.SEM = ? "
+ "AND c.MABB = m.MABB AND m.KABB = ?");**
giveCategories.setString(1, abb);
**giveModule.setString(1, abb);**
ResultSet categoriesGiven= giveCategories.executeQuery();
while (categoriesGiven.next()) {
categories.add(categoriesGiven.getString("NAME") + " (" +
categoriesGiven.getString("KABB") + ")");
}
**for (int i = 0; i < 6; i++) {
currentCategory = categories.get(i);
line.add(currentCategory);
giveModule.setString(3, currentCategory);
for (int j = 0; j < 6; j++) {
Integer seme = new Integer(j);
seme++;
giveModule.setString(2, seme.toString());
ResultSet current Modules = giveModules.executeQuery();
while (currentModules.next()) {
zeile.add(currentModules.getString("MABB"));
}
}
line.add("Sum");
curriculum.add(line);
line= new ArrayList();
}**
*A bunch of other stuff happens*
} catch (Exception e) {
System.out.println("getStudyingPlan has encountered an error.");
e.printStackTrace();
} finally {
if (con != null) {
try {
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return curriculum;
}
The error I keep getting says:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "st" at line 1, column 73
so I'm assuming that there is an error in the PreparedStatement somewhere, but I can't seem to find it. Any help, even just a nudge, would be greatly appreciated while I'm trying to figure out the problem by myself.
Your query is running together, put a space after the c.
"FROM MODULE m, STUDIES st, CURRICULUM c" +
"WHERE st.SKABB = ? AND c.SEM = ? "
Should become
"FROM MODULE m, STUDIES st, CURRICULUM c " + // Note space
"WHERE st.SKABB = ? AND c.SEM = ? "

how to correctly MySQL "desc table" via java connectivity

I am actually building a project where the names of tables present in databases of mysql are displayed in a list in java.
user selects a table from a list and the description of that table in given using "desc tablename" command.
The problem is, it is supposed to get every field in table but it only gets first field. Below i have explained it more, but first heres my code-:
try {
int rowCount = tableModel.getRowCount();
for (int i = 0; i < rowCount; i++) {
tableModel.removeRow(i);
}
String z = jList2.getSelectedValue().toString();
try {
Class.forName("java.sql.DriverManager");
} catch (ClassNotFoundException e) {
timeget();
jTextArea4.append(now + ": " + "/ Failed in getting Driver \n Error Message: " + e.getMessage() + " / \n \n");
JOptionPane.showMessageDialog(this, e.getMessage());
}
DriverManager.getConnection("jdbc:mysql://localhost:" + GlobalParams.portvar + "/", "" + k, "" + j);
stmnt = (Statement) con.createStatement();
String query = "desc " + z;
jTextArea5.append(now + ": " + "/ desc " + z + "; / \n \n");
ResultSet rs = stmnt.executeQuery(query);
String[] cnames = {"Field", "Type", "Null", "Key", "Extra"};
tableModel.setColumnIdentifiers(cnames);
jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
jTable1.setFillsViewportHeight(true);
if (rs.next()) {
String field = rs.getString("Field");
String type = rs.getString("type");
String nullinfo = rs.getString("null");
String key = rs.getString("key");
String extra = rs.getString("extra");
tableModel.addRow(new Object[]{field, type, nullinfo, key, extra});
}
catch(SQLException e){//some blabla}
Now for detailing into problem->
Say from the list, i select a table called "city". Originally, it has four fields- ID, Name, Population, CountryCode. But in my jTable, only "ID" appears.
the code...
int rowCount = tableModel.getRowCount();
for (int i = 0; i < rowCount; i++) {
tableModel.removeRow(i);
}
...is simply to remove fields of old table when a new table is selected from list.
Hope i clarified my prob.
Please help regarding this. Thanks.
the problem is in this
if (rs.next()) {
String field = rs.getString("Field");
String type = rs.getString("type");
String nullinfo = rs.getString("null");
String key = rs.getString("key");
String extra = rs.getString("extra");
tableModel.addRow(new Object[]{field, type, nullinfo, key, extra});
}
you are not continuing the loop
change the if loop to while loop
while(rs.next()) {
String field = rs.getString("Field");
String type = rs.getString("type");
String nullinfo = rs.getString("null");
String key = rs.getString("key");
String extra = rs.getString("extra");
tableModel.addRow(new Object[]{field, type, nullinfo, key, extra});
}

MySQL command SELECT values in column - JDBC

I'm using MySQL commands via JDBC (Java) to make changes to my database. I have implemented the following method to return the values of a column. The goal is to have the location in the column (row) correspond with their location in the array (index). This works with String columns, but with numerical columns, the ResultSet seems to place them in ascending order, thus making their positioning in the returned String array not reflect their positioning in the column. 'rs' is a ResultSet reference variable.
public String[] getColumnContents(String tableName, String columnName) {
String sql = "SELECT " + columnName + " FROM " + tableName;
String[] results = new String[SQLManager.getColumnLength(tableName, columnName)];
try {
rs = statement.executeQuery(sql);
for (int counter = 0; rs.next(); counter++) {
results[counter] = rs.getString(columnName);
}
} catch (SQLException e) {
e.printStackTrace();
}
return results;
}
It's as simple as adding an ORDER BY clause to the SQL command. Here's my working method:
public String[] getColumnContents(String tableName, String columnName) {
String sql = "SELECT " + columnName + " FROM " + tableName + " ORDER BY " + columnName1 + " ASC, " + columnName2 + " ASC";
String[] results = new String[SQLManager.getColumnLength(tableName, columnName)];
try {
rs = statement.executeQuery(sql);
for (int counter = 0; rs.next(); counter++) {
results[counter] = rs.getString(columnName);
}
} catch (SQLException e) {
e.printStackTrace();
}
return results;
}

Upgrade SQLite database from one version to another?

I am getting an error from Logcat saying that a certain column (in my SQLiteOpenHelper subclass) does not exist. I thought I could upgrade the database by changing the DATABASE_CREATE string. But apparently not, so how can I (step-by-step) upgrade my SQLite Database from version 1 to version 2?
I apologize if the question seems "noobish", but I am still learning about Android.
#Pentium10 This is what I do in onUpgrade:
private static final int DATABASE_VERSION = 1;
....
switch (upgradeVersion) {
case 1:
db.execSQL("ALTER TABLE task ADD body TEXT");
upgradeVersion = 2;
break;
}
...
Ok, before you run into bigger problems you should know that SQLite is limited on the ALTER TABLE command, it allows add and rename only no remove/drop which is done with recreation of the table.
You should always have the new table creation query at hand, and use that for upgrade and transfer any existing data. Note: that the onUpgrade methods runs one for your sqlite helper object and you need to handle all the tables in it.
So what is recommended onUpgrade:
beginTransaction
run a table creation with if not exists (we are doing an upgrade, so the table might not exists yet, it will fail alter and drop)
put in a list the existing columns List<String> columns = DBUtils.GetColumns(db, TableName);
backup table (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
create new table (the newest table creation schema)
get the intersection with the new columns, this time columns taken from the upgraded table (columns.retainAll(DBUtils.GetColumns(db, TableName));)
restore data (String cols = StringUtils.join(columns, ",");
db.execSQL(String.format(
"INSERT INTO %s (%s) SELECT %s from temp_%s",
TableName, cols, cols, TableName));
)
remove backup table (DROP table 'temp_" + TableName)
setTransactionSuccessful
.
public static List<String> GetColumns(SQLiteDatabase db, String tableName) {
List<String> ar = null;
Cursor c = null;
try {
c = db.rawQuery("select * from " + tableName + " limit 1", null);
if (c != null) {
ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
}
} catch (Exception e) {
Log.v(tableName, e.getMessage(), e);
e.printStackTrace();
} finally {
if (c != null)
c.close();
}
return ar;
}
public static String join(List<String> list, String delim) {
StringBuilder buf = new StringBuilder();
int num = list.size();
for (int i = 0; i < num; i++) {
if (i != 0)
buf.append(delim);
buf.append((String) list.get(i));
}
return buf.toString();
}
Here is how I upgrade my database.
In a previous version of my app, the gameType column doesn't exist. In the new version, it does.
void upgradeDatabase() throws IOException {
try {
String column = DatabaseConstants.GAME_TYPE_COLUMN_NAME; // gameType
String table = DatabaseConstants.RECORDS_TABLE;
String query = String.format("SELECT %s FROM %s LIMIT 1", column, table);
database.rawQuery(query, null);
return;
}
catch (Exception e) {
// Column doesn't exist. User had old version of app installed, so upgrade database.
}
// Save all old data
String query = "SELECT * FROM " + DatabaseConstants.USERS_TABLE;
Cursor c = database.rawQuery(query, null);
List<List<Object>> values1 = new ArrayList<List<Object>>();
if (c.moveToFirst()) {
while (!c.isAfterLast()) {
List<Object> record = new ArrayList<Object>();
record.add(c.getInt(0));
record.add(c.getString(1));
values1.add(record);
c.moveToNext();
}
}
c.close();
query = "SELECT * FROM " + DatabaseConstants.RECORDS_TABLE;
c = database.rawQuery(query, null);
List<List<Object>> values2 = new ArrayList<List<Object>>();
if (c.moveToFirst()) {
while (!c.isAfterLast()) {
List<Object> record = new ArrayList<Object>();
record.add(c.getInt(0));
record.add(c.getInt(1));
record.add(c.getInt(2));
record.add(c.getInt(3));
values2.add(record);
c.moveToNext();
}
}
c.close();
// Copy empty database with new schema
copyDatabase();
// Restore all old data
for (List<Object> record : values1) {
ContentValues cv = new ContentValues();
cv.put(DatabaseConstants.ID_COLUMN_NAME, (Integer) record.get(0));
cv.put(DatabaseConstants.USERNAME_COLUMN_NAME, record.get(1).toString());
database.insert(DatabaseConstants.USERS_TABLE, null, cv);
}
for (List<Object> record : values2) {
ContentValues cv = new ContentValues();
cv.put(DatabaseConstants.USER_ID_COLUMN_NAME, (Integer) record.get(0));
cv.put(DatabaseConstants.GAME_TYPE_COLUMN_NAME, GameType.CLASSIC.name());
cv.put(DatabaseConstants.WINS_COLUMN_NAME, (Integer) record.get(1));
cv.put(DatabaseConstants.LOSSES_COLUMN_NAME, (Integer) record.get(2));
cv.put(DatabaseConstants.TIES_COLUMN_NAME, (Integer) record.get(3));
database.insert(DatabaseConstants.RECORDS_TABLE, null, cv);
}
}
Here's the code to copy the database file. The database is initially empty, and I created it outside my app. (I used a program called Navicat for SQLite.)
public DatabaseHelper(Context context) {
super(context, DatabaseConstants.DATABASE_NAME, null, 1);
this.context = context;
databasePath = context.getDatabasePath(DatabaseConstants.DATABASE_NAME).getPath();
}
void copyDatabase() throws IOException {
InputStream is = context.getAssets().open(DatabaseConstants.DATABASE_NAME); // data.db
OutputStream os = new FileOutputStream(databasePath);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
// Close the streams.
os.flush();
os.close();
is.close();
}
Wouldn't something like the following be easier for the vast majority of cases? Just add the new column for each version upgrade:
private static final String DATABASE_ALTER_TEAM_1 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_COACH + " string;";
private static final String DATABASE_ALTER_TEAM_2 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_STADIUM + " string;";
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL(DATABASE_ALTER_TEAM_1);
}
if (oldVersion < 3) {
db.execSQL(DATABASE_ALTER_TEAM_2);
}
}
For a bit more on this, check out this blog.

Categories