I have a Java Swing application that accesses a Postgres database using a simple Singleton Pattern:
public class DatabaseConnection {
private static final String uname = "*******";
private static final String pword = "*******";
private static final String url = "*******************************";
Connection connection;
// load jdbc driver
public DatabaseConnection(){
try{
Class.forName("org.postgresql.Driver");
establishConnection();
} catch (ClassNotFoundException ce) {
System.out.println("Could not load jdbc Driver: ");
ce.printStackTrace();
}
}
public Connection establishConnection() {
// TODO Auto-generated method stub
try{
connection = DriverManager.getConnection(url, uname, pword);
} catch (SQLException e){
System.out.println("Could not connect to database: ");
e.printStackTrace();
}
return connection;
}
}
public class SingletonConnection {
private static DatabaseConnection con;
public SingletonConnection(){}
public static DatabaseConnection instance(){
assert con == null;
con = new DatabaseConnection();
return con;
}
}
This is my user table created by Pgadmin3 (hence the ugly upper cases):
CREATE TABLE "user"
(
id serial NOT NULL,
"userRoleId" integer NOT NULL,
"employeeId" bigint NOT NULL,
"subjectId" bigint NOT NULL,
username text NOT NULL,
cryptpwd text NOT NULL,
"userStatusId" integer NOT NULL,
md5pwd text NOT NULL,
CONSTRAINT pk_user PRIMARY KEY (id),
CONSTRAINT "subjectId" FOREIGN KEY ("subjectId")
REFERENCES subject (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT user_employee_id FOREIGN KEY ("employeeId")
REFERENCES employee (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "user_userRole_id" FOREIGN KEY ("userRoleId")
REFERENCES "userRole" (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "user_userStatus_id" FOREIGN KEY ("userStatusId")
REFERENCES "userStatus" (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "unique_user_userName" UNIQUE (username)
)
Since this application will be run on many machines in a local network, I would like to have only a single connection instance per specific user. That is, if userA logs in from one machine, and userA logs in from another machine moments later, notifications should appear on both machines with the second log in having the option to continue with the connection - in which case, the existing connection is dropped/lost.
I imagine I'd have to add a new column (logged_on boolean) in my user table ... in which case the second log in is handled by finding the value of logged_on and acting appropriately. My question is, how then will I be able to close the first connection? How can I maintain a maximum of one connection - per user - at database level?
Ok, this is what I'm working on. Surprisingly, I was thinking of something along the lines you mentioned Zamezela ... I haven't got it working yet, but I think this should work.
My user table:
CREATE TABLE "user"
(
id serial NOT NULL,
"userRoleId" integer NOT NULL,
"employeeId" bigint NOT NULL,
"subjectId" bigint NOT NULL,
username text NOT NULL,
cryptpwd text NOT NULL,
"userStatusId" integer NOT NULL,
md5pwd text NOT NULL,
"loggedIn" boolean NOT NULL DEFAULT false,
CONSTRAINT pk_user PRIMARY KEY (id),
CONSTRAINT "subjectId" FOREIGN KEY ("subjectId")
REFERENCES subject (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT user_employee_id FOREIGN KEY ("employeeId")
REFERENCES employee (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "user_userRole_id" FOREIGN KEY ("userRoleId")
REFERENCES "userRole" (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "user_userStatus_id" FOREIGN KEY ("userStatusId")
REFERENCES "userStatus" (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT "unique_user_userName" UNIQUE (username)
)
I've created a table that records each and every user login. Will help track down on user activity:
CREATE TABLE "userLoginHistory"
(
"userId" integer NOT NULL,
_datetime timestamp without time zone NOT NULL,
hostname text NOT NULL,
"osUsername" text NOT NULL,
id bigserial NOT NULL,
CONSTRAINT "pk_userLoginHistory" PRIMARY KEY (id),
CONSTRAINT "userLoginHistory_user_id" FOREIGN KEY ("userId")
REFERENCES "user" (id) MATCH FULL
ON UPDATE RESTRICT ON DELETE RESTRICT DEFERRABLE INITIALLY IMMEDIATE
)
I now have three main Stored functions thus far ... may add on to them tomorrow. Getting late.
First one involves requesting for a user login. This returns the user id, role, whether someone is logged on on this user account, and whether this user is active:
create type userLoginRequestReturnType as
(
userId integer, -- user.id
userRoleId integer, -- user.roleId
loggedIn boolean, -- user.loggedIn
userActive boolean -- whether user is active
);
CREATE OR REPLACE FUNCTION "user_login_request"(usernameIn text, passwordIn text)
returns setof userLoginRequestReturnType as
$$
declare
user_Id integer;
user_RoleId integer;
user_StatusId integer;
user_loggedIn boolean;
user_Active boolean;
sql text;
begin
user_Active = false;
select into user_Id, user_RoleId, user_StatusId, user_loggedIn id, "userRoleId", "userStatusId", "loggedIn" from "user" where username = usernameIn and cryptpwd = crypt(passwordIn, cryptpwd);
if (user_id > 0) then -- record found
select into user_Active "user_is_active"(user_StatusId);
else
user_id = 0;
user_RoleId = 0;
user_loggedIn = false;
user_Active = false;
end if;
sql = 'select ' || user_Id || ', ' || user_RoleId || ', ' || user_loggedIn || ', ' || user_Active ||';';
return query execute sql;
end;
$$ language 'plpgsql';
This is passed to the front end. If user_loggedIn is true, and all the other attributes support a successful log in, then the front end will notify the user that there is an existing connection, and whether to continue (disconnecting the existing connection). If it is false, then it just continues (without any prompt) to this function:
CREATE OR REPLACE FUNCTION "user_login_complete"(userIdIN integer, hostnameIN text, osUsernameIN text)
returns bigint as
$$
declare
currentTime timestamp without time zone;
userLoginHistoryId bigint;
begin
-- update user.loggedIn
update "user" set "loggedIn" = true where id = userIdIN;
-- insert into userLoginHistory
currentTime = NOW()::timestamp without time zone;
insert into "userLoginHistory" ("userId", _datetime, hostname, "osUsername") values (userIdIN, currentTime, hostnameIN, osUsernameIN);
select into userLoginHistoryId currval('"userLoginHistory_id_seq"');
return userLoginHistoryId;
end;
$$ language 'plpgsql';
The userLoginHistoryId is stored on the front end, since I'm using an MVC architecture for my Java Swing project, my abstract Model Class will call the following function in its constructor. I have taken your advice and will close the connection in each method.
-- function to check if the current logged in session is the last one recorded in database
-- to be run before each connection to the database as per userId
-- new userLoginHistoryId must be inserted into table userLoginHistory, and the id PK value stored in the front end
--
-- returns: true, if current session is the last session recorded in table userLoginHistory for this user_autosuggest_by_ID
-- : false, if another login session has been recorded.
-- MUST BE EXECUTED BEFORE EACH AND EVERY DATABASE TRANSACTION!!!!!
CREATE OR REPLACE FUNCTION "user_login_session_check"(userIdIN integer, userLoginHistoryIdIN bigint)
returns boolean as
$$
declare
results boolean;
userLoginHistoryId bigint;
begin
results = true;
select into userLoginHistoryId id from "userLoginHistory" where "userId" = userIdIN ORDER BY id DESC LIMIT 1;
if (userLoginHistoryIdIN = userLoginHistoryId) then
results = true;
else
results = false;
end if;
end;
$$ language 'plpgsql';
Will test tomorrow and hopefully it works fine. Please feel free to comment.
Thanks.
#greatkalu your problem is much deeper and very hard achievable, I will suggest you some approach: when user log in you should update two fields(last_access_timestamp, computer_id) and for every access to the database you should update last_access_timestamp. computer_id and last_access_time should be valid maybe 1 hour or less depends of the use of the application. when other person tries to login with same user_id then if now() - 1 hour < last_access_timestamp then that user should not be grant access.
computer_id is generated from application and for every computer should be unique and always generated same computer_id.
I hope this will help
Related
I am making a javafx (intelliJ with java jdk 11) app using SQLite version 3.30.1 with DB Browser for SQLite.
I have a table called "beehives" and each beehive can have diseases (stored in the table "diseases").
this is my "beehives" table:
CREATE TABLE "beehives" (
"number" INTEGER NOT NULL,
"id_apiary" INTEGER NOT NULL DEFAULT -2,
"date" DATE,
"type" TEXT,
"favorite" BOOLEAN DEFAULT 'false',
PRIMARY KEY("number","id_apiary"),
FOREIGN KEY("id_apiary") REFERENCES "apiaries"("id") ON DELETE SET NULL
);
this is my "diseases" table:
CREATE TABLE "diseases" (
"id" INTEGER NOT NULL,
"id_beehive" INTEGER NOT NULL,
"id_apiary" INTEGER NOT NULL,
"disease" TEXT NOT NULL,
"treatment" TEXT NOT NULL,
"start_treat_date" DATE NOT NULL,
"end_treat_date" DATE,
PRIMARY KEY("id"),
FOREIGN KEY("id_beehive","id_apiary") REFERENCES "beehives"("number","id_apiary") ON UPDATE CASCADE
);
this is my "apiaries" table in case you need it:
CREATE TABLE "apiaries" (
"id" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"address" TEXT,
PRIMARY KEY("id")
);
Everything works fine, but when I update a beehive (for example when I update the "number", which is the primary key in beehives table) the diseases does not update the number. The result is that the diseases get some kind of disconnected since the beehive change his "number" correctly, but the disease doesn't update it. There is no error message.
My java method that calls the update is:
public void updateBeehiveInDB(Beehives newBeehive,Beehives oldBeehive){
try {
s = "UPDATE beehives SET number=?, id_apiary=?, date=?, type=?, favorite=? WHERE number=? and id_apiary=? ";
preparedStatement = connection.prepareStatement(s);
preparedStatement.setInt(1, newBeehive.getNumber());
preparedStatement.setInt(2, newBeehive.getId_apiary());
preparedStatement.setDate(3, newBeehive.getDate());
preparedStatement.setString(4, newBeehive.getType());
preparedStatement.setBoolean(5, newBeehive.isFavorite());
preparedStatement.setInt(6, oldBeehive.getNumber());
preparedStatement.setInt(7,oldBeehive.getId_apiary());
int i = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
I tried to check if foreign keys are "on" following the SQLite documentation here, but my English is not good enough and I am using DB Manager. So no idea how to check if this is on, or how to turn it on manually.
What can I do to update the diseases "id_beehives" when I update "number" on beehives table?
The problem was that i am using a composite foreign key and i need to implement it correctly on other tables too even if i was not using them yet in this new project. Was very hard to find the problem because intellij normally show all the SQL error messages, but in this case, it was not showing anything. But when i tried to do the SQL sentence manually in the DB Browser, there i got an error message and was able to fix it.
Also had to activate foreign key on the connection:
public Connection openConnection() {
try {
String dbPath = "jdbc:sqlite:resources/db/datab.db";
Class.forName("org.sqlite.JDBC");
SQLiteConfig config = new SQLiteConfig();
config.enforceForeignKeys(true);
connection = DriverManager.getConnection(dbPath,config.toProperties());
return connection;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
I got two Tables like this: Enrollment and Student
create table [LECTURE_DB].[dbo].[ENROLLMENT](
[EXAM_PASSED] bit null default ((0)),
[EXAM_TAKEN] bit null default ((0)),
[YEAR] int not null,
[LECTURE_ID] numeric(19) not null,
[STUDENT_ID] numeric(19) not null,
constraint [PK__ENROLLME__FE468F5B2739D489]
primary key (
[YEAR],
[LECTURE_ID],
[STUDENT_ID]
)
)
create table [LECTURE_DB].[dbo].[STUDENT](
[ID] numeric(19) identity(1, 1) not null,
[FIRSTNAME] varchar(255) null,
[GENDER] varchar(255) null,
[LASTNAME] varchar(255) null,
[YEAR_OF_BIRTH] int null,
constraint [PK__STUDENT__3214EC273493CFA7]
primary key ([ID])
)
I now try to Update a bunch of Enrollments (the exam_passed column) with some lastnames, an Lecture_ID and a year. From this I got the idea to use the joined Table.
private void updateStudentExamPassed(boolean passed, int lidx, int year, String... studentName) {
Enrollment enrollment = Enrollment.ENROLLMENT;
Student student = Student.STUDENT;
Table<?> joined = enrollment.leftJoin(student).on(enrollment.STUDENT_ID.eq(student.ID));
ctx.update(joined)
.set(enrollment.EXAM_PASSED, passed)
.where(student.LASTNAME.in(studentName))
.and(enrollment.YEAR.eq(year))
.and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
.execute();
}
But I get an DataAccessException on the .execute()
Exception in thread "main" org.jooq.exception.DataAccessException: SQL [update [LECTURE_DB].[dbo].[ENROLLMENT] left outer join [LECTURE_DB].[dbo].[STUDENT] on [LECTURE_DB].[dbo].[ENROLLMENT].[STUDENT_ID] = [LECTURE_DB].[dbo].[STUDENT].[ID] set [LECTURE_DB].[dbo].[ENROLLMENT].[EXAM_PASSED] = ? where ([LECTURE_DB].[dbo].[STUDENT].[LASTNAME] in (?, ?) and [LECTURE_DB].[dbo].[ENROLLMENT].[YEAR] = ? and [LECTURE_DB].[dbo].[ENROLLMENT].[LECTURE_ID] = ?)]; Falsche Syntax in der Nähe des left-Schlüsselworts.
at org.jooq_3.12.1.SQLSERVER2014.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2717)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:755)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:383)
at org.jooq.impl.AbstractDelegatingQuery.execute(AbstractDelegatingQuery.java:119)
at de.esteam.lecturedb.jooq.tasks.RecordFeaturesTask.updateStudentExamPassed(RecordFeaturesTask.java:42)
at de.esteam.lecturedb.jooq.tasks.RecordFeaturesTask.run(RecordFeaturesTask.java:28)
at de.esteam.lecturedb.jooq.common.LectureDBAnalysis.run(LectureDBAnalysis.java:100)
at de.esteam.lecturedb.jooq.common.LectureDBAnalysis.main(LectureDBAnalysis.java:56)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Falsche Syntax in der Nähe des left-Schlüsselworts.
The Documentation did not help me since the condition relies on another table. Is there any hope to get this to work or do I need to get each Enrollment by it self and update it single handedly?
Using vendor specific syntax
The question you've linked is about MySQL. SQL Server does not support this kind of syntax, but you can achieve an equivalent semantics by using the UPDATE .. FROM clause. I.e. try this:
ctx.update(enrollment)
.set(enrollment.EXAM_PASSED, passed)
.from(joined)
.where(student.LASTNAME.in(studentName))
.and(enrollment.YEAR.eq(year))
.and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
.execute();
Notice that a LEFT JOIN does not make any sense here if you're turning it again into an INNER JOIN by having a predicate on the student table in your WHERE clause.
Using standard syntax
I personally prefer using standard SQL syntax whenever it is possible in these cases, as these UPDATE .. FROM or UPDATE .. JOIN statements can often be replaced by IN or EXISTS predicates. For example:
ctx.update(enrollment)
.set(enrollment.EXAM_PASSED, passed)
.where(enrollment.STUDENT_ID.in(
select(student.ID)
.from(student)
.and(student.LASTNAME.in(studentName))
))
.and(enrollment.YEAR.eq(year))
.and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
.execute();
My javaFx application has many tables with editable table cells to populate data from sql database.I also want to make changes in database after data editing through table cells.According to this toturial "https://docs.oracle.com/javafx/2/ui_controls/table-view.htm"
I have created my editable table cell with the following code.
item_price_col.setCellValueFactory(
new PropertyValueFactory("price")
);
item_price_col.setCellFactory(TextFieldTableCell.forTableColumn());
item_price_col.setOnEditCommit(
new EventHandler<CellEditEvent<Item, String>>() {
#Override
public void handle(CellEditEvent<Item,String> t) {
String old_price=t.getOldValue();
((Item) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setPrice(t.getNewValue());
String new_price=t.getNewValue();
System.out.println("Old Price:"+old_price);
System.out.println("New Price:"+new_price);
}
}
);
But it doesn't make any changes in database after editing.So,I think have to write update Query inside of that handle method.But I can only know old value and new value. I can't make query statement like that "update item set price=new_price where price=old_price".If I update a single price of a item to new value,every items in my item table that have the same price with my edited item will make changes to new price value.Are there any ways to solve this problem?
Here is my item table structure.
item | CREATE TABLE `item` (
`code` int(11) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`price` varchar(50) NOT NULL,
`whole_sale_price` varchar(50) NOT NULL,
`orginal_price` varchar(50) DEFAULT NULL,
PRIMARY KEY (`code`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
Keep an id field to your item as it is given in the database.
If you have not primary or unique key in the database probably you made some architectural mistake. Anyway there is a row id specified in some database servers.
private int id; // id field for item object.
While updating include id as condition.
update sometable set price = item.getPrice() where id = item.getId();
I know sql is not well written but I hope you'll get it
And you don't have to show value of id field in your table grid.
This technique is used in most systems
EDITED 2015.12.18
You have code column in the table. Retrieve by jdbc into your item object's id field.
There is an example
http://www.tutorialspoint.com/jdbc/jdbc-update-records.htm
This is my code for executing in my java program:
public static void createBooksTablesAndSetPK() {
String selectDB = "Use lib8";
String createBooksTable = "Create table IF NOT EXISTS books (ID int,Name varchar(20),ISBN varchar(10),Date date )";
String bookTablePK = "ALTER TABLE BOOKS ADD PRIMARY KEY(id)";
Statement st = null;
try (
Connection con = DriverManager.getConnection(dbUrl, "root", "2323");) {
st = con.createStatement();
st.execute(selectDB);
st.execute(createBooksTable);
st.execute(bookTablePK);
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
I cat use IF NOT EXIST for creating databasesand tables to prevent creating duplicate database and tables and corresponding errors.
But i don't know how prevent Multiple primary key error, because program may call createBooksTablesAndSetPK() multiple times.
Error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Multiple primary key defined
The column Book_id is not existing in your case. You are creating a table with ID as the column and then updating the table with a PRIMARY KEY constraint on a column that is not existing.
Create table IF NOT EXISTS books (ID int,Name varchar(20),ISBN varchar(10),Date date )
ALTER TABLE BOOKS ADD PRIMARY KEY(BOOK_id)
Try running these statements on a MySQL command prompt (or MySql Workbench) and the see the error.
You need change the alter table command like this.
ALTER TABLE BOOKS ADD BOOK_id VARCHAR( 255 ), ADD PRIMARY KEY(BOOK_id);
My database had a lot of parent and child tables.The tables contains the foreign key which has the link with the parent table.I wants to get the information of parent table of the child table using java?How can I achieve that?
For ex,consider the student and mark table,
The student table contains the information like studentID,name.
studentID-Primary key
The marks table contains the markId,studentId,Sub1,sub2,sub3 etc
markId-Primarykey
studentID-Foreignkey refers Student table
My table creation queries are,
CREATE TABLE `Student12` (
`studentId` SMALLINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`studentId`)
)
ENGINE = InnoDB;
CREATE TABLE `Marks` (
`markId` SMALLINT NOT NULL AUTO_INCREMENT,
`subject1` SMALLINT NOT NULL,
`subject2` SMALLINT NOT NULL,
`studentId` SMALLINT NOT NULL,
PRIMARY KEY (`markId`),
CONSTRAINT `FK_Marks_Student` FOREIGN KEY `FK_Marks_Student` (`studentId`)
REFERENCES `Student12` (`studentId`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
)
ENGINE = InnoDB;
If I give the mark table name as input, how can I get its parent or super table name student and information about student table?Any help should be appreciable.
It totally depends on the way tables are created. Foreign keys are not mandatory to create, they could be a simple column in one table with no explicit relationship to the other table. If you are very sure that the links are created explicitly (the foreign keys are defined) then you could use information_schema. But if there is no foreign key defined (which is true in most of the databases I have seen), then there is no way for you to find the links inside the database. You have to look into the code (if there is any available) and try to find a clue.
The JDBC DatasetMetaData interface provides a couple of methods that may help. (The following text is copied from the javadoc.
ResultSet getExportedKeys(String catalog, String schema, String table)
Retrieves a description of the foreign key columns that reference the given table's primary key columns (the foreign keys exported by a table).
ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable)
Retrieves a description of the foreign key columns in the given foreign key table that reference the primary key or the columns representing a unique constraint of the parent table (could be the same or a different table).
Of course, these can only work if the relevant columns have been declared as foreign keys in the SQL table DDL.
You can use the DatabaseMetaData to retrieve informations about foreign keyes
and the referenced Tables. Im not sure if it works with all kinds of MySql Tables.
The principle is to use the follwing code (not tested) to retrieve information about the super tables
ResultSet rs = null;
DatabaseMetaData dm = conn.getMetaData( );
// get super tables of table marks
ResultSet rs = dm.getSuperTables( null , null, "marks" );
while( rs.next( ) ) {
System.out.println(String.format("Table Catalog %s", rs.getString("TABLE_CAT") );
System.out.println(String.format("Table Schema %s", rs.getString("TABLE_SCHEM") );
System.out.println(String.format("Table Name %s", rs.getString("TABLE_NAME") );
System.out.println(String.format("Table Name %s", rs.getString("SUPERTABLE_NAME") );
}
You can use thes informations to get additional informations about the referenced table
and the foreigen and referenced primary keys:
ResultSet rs = dm.getCrossReference( null , null , "student" , null , null , "marks" );
System.out.println(String.format("Exported Keys Info Table %s.", "marks"));
while( rs.next( ) ) {
String pkey = rs.getString("PKCOLUMN_NAME");
String ptab = rs.getString("PKTABLE_NAME");
String fkey = rs.getString("FKCOLUMN_NAME");
String ftab = rs.getString("FKTABLE_NAME");
System.out.println("primary key table = " + ptab);
System.out.println("primary key = " + pkey);
System.out.println("foreign key table = " + ftab);
System.out.println("foreign key = " + fkey);
}
And finally you can retrieve the information about the super table by
ResultSet rs = dm.getTables(null,null,"student" ,null);
System.out.println("Table name:");
while (rs.next()){
String table = rs.getString("TABLE_NAME");
System.out.println(table);
}