Java JDBC adding automatic value to database - java

I'm working with Java JDBC with Apache Derby data base.
I have a table called `company`` with the values :
id, comp_name, password, email.
This method should create a new row of company with name, password, and email received from the user but the ID should be given automatically from the database and increment itself each time a new company is added to the database.
I just can't figure out how to make this work, I obviously get a error
"column 'ID' cannot accept a NULL value."
because the update occours before the ID is setted.
Code:
public void createCompany(Company company) {
Connection con = null;
try {
con = ConnectionPool.getInstance().getConnection();
String sql = "INSERT INTO company (comp_name, password, email) VALUES (?,?,?)";
PreparedStatement pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, company.getCompName());
pstmt.setString(2, company.getPassword());
pstmt.setString(3, company.getEmail());
pstmt.executeUpdate();
ResultSet rs = pstmt.getGeneratedKeys();
rs.next();
company.setId(rs.getLong(1));
pstmt.getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionPool.getInstance().returnCon(con);
}

During creation of that table you have to write following DDL
CREATE TABLE MAPS
(
comp_id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
comp_name VARCHAR(24) NOT NULL,
password VARCHAR(26)
)
Ref : https://db.apache.org/derby/docs/10.0/manuals/develop/develop132.html

You're doing almost everything right, you just need to let the database assign an unique ID to each inserted row:
CREATE TABLE my_table (
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
...
);

A problem could be that you made a mistake by creating your table.
You could create your table like this:
CREATE TABLE company
(
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
comp_name VARCHAR(50),
email VARCHAR(50),
password VARCHAR (50)
)
IF you want other values to be not NULL you could add NOT NULL to their lines:
password VARCHAR (50) NOT NULL
Delte your old table and execute the the SQl above on your DB. After that you can use your code without changes.

Related

Cannot delete or update a parent row - Java

I teacher is trying to delete a row, which is used by a student.
But how can I delete this row anyway?
If the teacher wants to delete the lesson it should delete it anyway?
This is the function I have for the delete query:
con = DriverManager.getConnection ("jdbc:mysql://localhost:3307/lessons","root","");
String query = "DELETE FROM lessons WHERE Number= ?";
PreparedStatement pst = con.prepareStatement(query);
pst.setString(1,txtFieldNumber.getText());
pst.executeUpdate();
.
CREATE TABLE UserLogin(
Number INTEGER,
UserNumberINTEGER,
FOREIGN KEY (Number) REFERENCES termin(Number),
FOREIGN KEY (UserNumber) REFERENCES User(UserNumber)
);
CREATE TABLE lessons(
Number INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
LName VARCHAR(20)
);
CREATE TABLE User(
Name VARCHAR (20),
UserNUmber INTEGER NOT NULL PRIMARY KEY
);
You have to perform 2 separate deletes and in the right order using the same value for the Number parameter.
First delete from UserLogin with
DELETE FROM UserLogin WHERE Number = ?
And then use the command you have today
DELETE FROM lessons WHERE Number = ?
If you want to be sure both statements gets executed properly you can use manual commit like this
You can't use setString when the underlying column is int
Assuming your txtFieldNumber.getText() returns a number in String format, Try the following
pst.setInt(1,Integer.parseInt(txtFieldNumber.getText()));
Update:
Based on your question edit, looks like you are first trying to delete primary key in lessons which is being referenced in UserLogin table. This is the reason you're facing the error.
To overcome this, you may want to first delete in UserLogin table and then delete the corresponding rows in lessons table.
String query = "DELETE FROM UserLogin WHERE Number= ?";
PreparedStatement pst = con.prepareStatement(query);
pst.setInt(1,Integer.parseInt(txtFieldNumber.getText()));
pst.executeUpdate();
String query2 = "DELETE FROM lessons WHERE Number= ?";
pst = con.prepareStatement(query2);
pst.setInt(1,Integer.parseInt(txtFieldNumber.getText()));
pst.executeUpdate();
This should solve your issue

PostgreSQL Insertion in JAVA via JSP Incrementing Primary Key

I am writing a JSP application where the user enters a food item and it is entered in a PostgreSQL database. I had no problems implementing this when the user manually had to enter the next primary key, but I removed this ability so that the primary key would be automatically assigned when the enter button is clicked. I would like the query to fetch the current maximum FID (Food ID) and set the new food item's FID to the previous + 1.
try {
conn = ConnectionProvider.getCon();
String sql = "select fid from project.food order by fid desc limit 1";
pst = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
status = pst.getResultSetType();
f.setFood_id(status + 1);
pst = conn.prepareStatement("insert into project.food values(?,?,?,?,?,?)");
pst.setInt(1, f.getFood_id());
pst.setString(2, f.getFood_name()); //set name
pst.setInt(3, f.getCount()); //set count
pst.setInt(4, f.getPrice_per_item()); //set price
pst.setInt(5, f.getThreshold()); //set threshold
pst.setString(6, "false");
status = pst.executeUpdate();
conn.close();
pst.close();
} catch (Exception ex) {
System.out.println(ex);
}
return status;
}
The first food item is successfully inserted into the database in row 1006, instead of the 7th row, which is the first available in the database. Additionally, the second insert fails due to the failure of the primary key to the incremented by 1. The program again tries to insert the next tuple in the same row and thus violates the primary key constraint.
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "food_pkey"
Detail: Key (fid)=(1006) already exists.
Make your primary key autoincrement in the database by declaring it SERIAL datatype (basically an auto incrementing INT) so a sequence is created to automatically assign values to it.
Then convert your update statement to specify all columns except for the primary key (i.e. insert into project.food(foo, bar, baz) values (?, ?, ?), and remove one ? placeholder and the pst.setInt(1,f.getFood_id()); line. This will insert values to all the other columns, and the primary key will be generated by the database.
This way you don't need to do a select when you want to insert (which was a really bad idea anyway), and you let the database do what it does best. You don't need to care about the value of the primary key after that.

H2 DB: How to check whether table schema is initialized programmatically?

I have a DB schema that creates several tables and fills them with data. I want to check whether db contains corresponding tables or not during app start. I could check for db file existence, but H2 creates db if it doesn't exist. So the only way, I think, is to check for tables existence.
Here is the code of how I initialize DB:
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:database/svc", "sa", "");
Statement st = conn.createStatement();
st.execute("CREATE TABLE IF NOT EXISTS table1 (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(100), record INT, record_date DATE, UNIQUE(name))");
st.execute("CREATE TABLE IF NOT EXISTS table2 (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(100), record INT, record_date DATE, UNIQUE(name))");
st.execute("CREATE TABLE IF NOT EXISTS daily_record_stat (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, date DATE, table1_id INT, table1_record INT, table2_id INT," +
" table2_record INT, total_record INT);");
st.execute("ALTER TABLE daily_record_stat ADD FOREIGN KEY (table1_id) REFERENCES table1(id);");
st.execute("ALTER TABLE daily_record_stat ADD FOREIGN KEY (table2_id) REFERENCES table2(id);");
st.execute("INSERT INTO table1 VALUES(1, 'non_existed_stub', 0, NULL)");
st.execute("INSERT INTO table2 VALUES(1, 'non_existed_stub', 0, NULL)");
conn.close();
As you see, I check for table existence before creation using IF NOT EXISTS statement. But then I run at the problem with ALTER and INSERT - these commands don's allow IF usage.
I tried to do the following:
Connection conn = DriverManager.getConnection("jdbc:h2:database/svc", "sa", "");
ResultSet meta = conn.getMetaData().getTables(null, null, "table1", null);
if(meta.next()) {
//do something
}
But meta.next() is false.
So how to check whether table schema is initialized? Or maybe this should be done some other way?
Not sure if that's what you mean by saying to check programmatically, buy you can try to use DatabaseMetaData.getTables(). This call will return ResultSet which you'll have to check programmatically. You can see what fields are returned in this ResultSet in corresponding section here. And meta data itself can be obtained by conn.getMetaData().
Following code should return all tables which names start with 'TABLE':
ResultSet meta = conn.getMetaData().getTables(null, null, "TABLE%", new String[]{"TABLE"});
while (meta.next()) {
System.out.println(meta.getString(3));
}
Note that you have to specify table name pattern in upper case. Also it's good to pass table types that you need, although it is optional.
This is a check I used to (re)create the H2 database:
// IMPORTANT A sorted list of table names.
private static final String[] REQUIRED_TABLES = { "USER", ... };
public static final String CREATE_USER = "create table USER (...)";
private boolean schemaExists() throws SQLException {
final List<String> requiredTables = Arrays.asList(REQUIRED_TABLES);
final List<String> tableNames = new ArrayList<String>();
final Connection conn = dataSource.getConnection();
try {
final Statement st = conn.createStatement();
final ResultSet rs = st.executeQuery("show tables");
while (rs.next()) {
tableNames.add(rs.getString("TABLE_NAME"));
}
rs.close();
st.close();
}
finally {
if (conn != null) { conn.close(); }
}
Collections.sort(tableNames);
return tableNames.equals(requiredTables);
}
private void initializeDatabase() throws SQLException {
final Connection conn = dataSource.getConnection();
try {
if (schemaExists()) {
return;
}
final Statement st = conn.createStatement();
st.executeUpdate(CREATE_USER);
conn.commit();
}
finally {
if (conn != null) { conn.close(); }
}
}
And you just call:
initializeDatabase();
Notice the list of required tables has to be sorted because I use List.equals() to compare two lists. It would probably be better to also programmatically sort the required tables list too.
It's not fool-proof (not checking if any table exists and if it should be altered) but it works for me.
Take a look at the SHOW command for other uses.

How to run mysql insert without duplicates in java

I have a method which insert a record to mysql database as bellow,
public boolean addOrganization(OrganizationDTO organizationDTO) {
Connection con = null;
try {
String insertOrganizationSQL = "INSERT INTO organizations (org_id, org_name) VALUES(?, ?)";
con = JDBCConnectionPool.getInstance().checkOut();
PreparedStatement insertOrgPS = (PreparedStatement) con.prepareStatement(insertOrganizationSQL);
insertOrgPS.setString(1, organizationDTO.getOrg_id());
insertOrgPS.execute();
return true;
} catch (Exception e) {
JDBCConnectionPool.getInstance().checkIn(con);
logger.error(e.getLocalizedMessage());
e.printStackTrace();
return false;
} finally {
JDBCConnectionPool.getInstance().checkIn(con);
}
}
database table,
CREATE TABLE `organizations` (
`org_id` varchar(5) NOT NULL,
`org_name` varchar(100) DEFAULT NULL,
`sys_dat_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user` varchar(100) NOT NULL,
PRIMARY KEY (`org_id`)
)
what I need is, when I insert a new record if, that is a duplicate exit the method without trying to insert and inform the user that it is a duplicate record. Is it possible to do without writing another method to search the record before inserting?
I would add a UNIQUE constraint to your table. For example, if org_name needs to be unique:
ALTER TABLE organizations ADD UNIQUE (org_name);
Then observe what's returned when you try to insert a duplicate record through Java. Add code to check for this, and if it occurs, display the message to your user.
Here is the reference documentation for ALTER TABLE.
Thats right, Alter table will surely help.
In your case, let say, both org_id and org_name is there, I would add unique in both, just avoid any confusion later.

How to retrieve row in DB Table just added now in Java

Table
id int(11) No auto_increment Change Drop Primary Index Unique Fulltext
email varchar(45) latin1_swedish_ci No Change Drop Primary Index Unique Fulltext
billpayment tinyint(1) No Change Drop Primary Index Unique Fulltext
dispatch tinyint(1) No Change Drop Primary Index Unique Fulltext
address varchar(75) latin1_swedish_ci Yes NULL Change Drop Primary Index Unique Fulltext
phone int(11) Yes NULL Change Drop Primary Index Unique Fulltext
created_at datetime No Change Drop Primary Index Unique Fulltext
totalbillamount float Yes NULL Change Drop Primary Index Unique Fulltext
Java Code:
sql = "insert into session_shopping (email,billpayment,dispatch,address,phone,created_at,totalbillamount) values(?,?,?,?,?,?,?)";
ps = (PreparedStatement) con.prepareStatement(sql);
ps.setString(1, email);
ps.setBoolean(2, false);
ps.setBoolean(3, false);
ps.setString(4, "");
ps.setInt(5, 0);
java.util.Date date = new java.util.Date();
long t = date.getTime();
java.sql.Date sqlDate = new java.sql.Date(t);
ps.setDate(6, sqlDate);
ps.setFloat(7, 00.0f);
int newId = ps.executeUpdate();
System.out.println("newId" + newId);
if (newId == 1) {
sql = "select * from session_shopping where id = ?";
ps = (PreparedStatement) con.prepareStatement(sql);
ps.setInt(1, newId);
ResultSet reS = ps.executeQuery();
Session s = new Session();
s.setId(reS.getInt("id"));
s.setEmail(reS.getString("email"));
System.out.println("retreived");
return s;
} else {
System.out.println("unable to save");
}
This code fails because int newId is boolean
What i want to do is. I want to retrieve the row which i added just now.
executeUpdate will return the number of rows affected, not the current row .
Try this
ResultSet rs = aStatement.executeQuery("SELECT LAST_INSERT_ID()");
while(rs.next())
{
key = rs.getInt(1);
}
The value returned by executeUpdate has nothing to do with your ID.
Before we go to getting your ID, you can start off by setting email in the Session from your email variable rather than pulling it back out of the database.
As things stand, the only way I can think of to get the newly inserted ID is by changing your SQL thus:
sql = "select max(id) from session_shopping";
This will give you problems if you get another insert before you pick out the maximum ID though. To prevent that, put the select in the same transaction as your insert.

Categories

Resources