Netbeans 7.0, entering values with composite primary key - java

I am working on a project with MySQL database Java GUI.
This is my SQL script
CREATE TABLE takenservice (
ResvID INT UNSIGNED NOT NULL,
ServID INT UNSIGNED DEFAULT 0 NOT NULL,
ServUsedDate DATETIME NOT NULL
, PayStat VARCHAR(6) DEFAULT Unpaid NOT NULL,
ServRecBy VARCHAR(7) NOT NULL,
PayRecBy VARCHAR(7),
Quantity SMALLINT DEFAULT 1 NOT NULL,
PRIMARY KEY (ResvID, ServID, ServUsedDate));
Alter table takenservice
add constraint foreign key (ResvId) references reservation (ResvID);
Alter table takenservice
add constraint foreign key (ResvId) references reservation (ResvID);
I created the entity classes with Netbeans 7.0 and created 4 classes:
Service
Reservation
ServiceTaken
ServiceTakenPK
but I cant enter values to the table and it gives me an error that I am trying to enter null values in as primary keys.
I have found the bug actually in Netbeans forum which is http://netbeans.org/bugzilla/show_bug.cgi?id=105084.
and accordingly I have added the following methods to the class ServiceTaken
public int getResvID() {
return takenservicePK.resvID;
}
public int getServID() {
return takenservicePK.servID;
}
public Date getServUsedDate() {
return takenservicePK.servUsedDate;
upon inserting a new entry in the table I get this error :
Error Code: 1048
Call: INSERT INTO takenservice (PayRecBy, ServRecBy, Quantity, PayStat, ServUsedDate, ResvID, ServID) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [ddd, ddd, 0, ddd, null, null, null]
What I can do to fix this ? Please help me with this I am running out of time =/

Please try using
System.out.println(yourqueryexecution stmt);
then check whether the statement can be executed in the DB;
Find whether it sends all the values to the db;
hope this works..

Related

#0001: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0)

I want to delete a row. My TABLES are 'goal' and 'contribute'.It shows above error.
Please tell immediately what's the problem.
Table structure is ,
//goal TABLE
CREATE TABLE `goal` (`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(555) NOT NULL,
`target_value` double NOT NULL,
`target_date` date NOT NULL,
`created_date` datetime NOT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8
COLLATE=utf8mb4_0900_ai_ci
//Contribute TABLE
CREATE TABLE `contribute`
(`id` int(11) NOT NULL AUTO_INCREMENT,`goal` int(11) NOT NULL,
`amount` double NOT NULL, `date` date NOT NULL,
PRIMARY KEY (`id`),KEY `idgoal_idx` (`goal`),
CONSTRAINT `fk` FOREIGN KEY (`goal`) REFERENCES `goal` (`id`))
ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8m
COLLATE=utf8mb4_0900_ai_ci
//Code
public static boolean delete(int id) {
try {
Connection con = DB.getConnection();
String sql = "ALTER TABLE 'goal' ADD CONSTRAINT 'fk' FOREIGN
KEY('goal') REFERENCES 'goal' ('id') ON DELETE CASCADE ";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, id);
ps.executeUpdate();
return true;
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
In my oppinion your code is bad. You are executing this
String sql = "ALTER TABLE 'goal' ADD CONSTRAINT 'fk' FOREIGN
KEY('goal') REFERENCES 'goal' ('id') ON DELETE CASCADE ";
every time you invoke this method. You should add constraints when creating the tables.
In order to delete a row from some table i suggest you to create a database procedure or function which does it and invoke it through java.
String sql = "{? = call your_schema.your_package.delete_object(?)}";
try (CallableStatement cs = con.createCallableStatement(sql)) {
cs.setInt(1, id);
cs.executeQuery();
}
This is just an example but i think this is the correct way to do it. In this procedure you accept your ID as parameter and delete the row there.
Here's two problem:
1.your sql doesn't contain any parameter keyword : ?
You use java set parameter ps.setInt(1, id), but your sql doesn't contain keyword ?
Example for parameter using ? :
PreparedStatement p = con.prepareStatement("select * from xxxTable where xxx = ?");
p.setString(1, xxx);
More details you can learn from mysql - java.sql.SQLException Parameter index out of range (1 > number of parameters, which is 0) - Stack Overflow
2.Your SQL maybe wrong
ALTER TABLE 'goal' ADD CONSTRAINT 'fk' FOREIGN
KEY('goal') REFERENCES 'goal' ('id') ON DELETE CASCADE
'goal' table doesn't contain 'goal' column.
it should be changed like:
ALTER TABLE `contribute`
ADD FOREIGN KEY (`goal`) REFERENCES `goal`(`id`) ON DELETE CASCADE ;
SQL Fiddle Demo Link

Java & SQL - Can't create duplicate values in my primary and foreign key

Go easy on me, middle school teacher taking a CS class. I've got a Java program that asks for user name, height, weight, does some calculations and gives results to the user. I now need to store this data in a database. I can get the data to store until I start using primary and foreign keys.
Here is the error I can't figure out:
Error: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL180429151131780' defined on 'USERPROFILE'.
Here is my table:
drop table stayfitapp.userdata;
drop table stayfitapp.userprofile;
drop schema stayfitapp restrict;
create schema stayfitapp;
create table stayfitapp.userprofile
(
profileName varchar(255) not null primary key,
profileGender varchar(255) not null
);
create table stayfitapp.userdata
(
profileAge double not null,
profileWeight double not null,
profileHeight double not null,
profileWaistCircumference double not null,
profileHipCircumference double not null,
profileName varchar(255),
foreign key (profileName) references stayfitapp.userprofile(profileName)
);
Here is the section of the "app" that writes to the table...
public void save(){
try {
String query = "insert into stayfitapp.userprofile" + "(profileName, profileGender)" + "values" + "(?,?)";
String query2 = "insert into stayfitapp.userdata" + "(profileAge, profileWeight, profileHeight, profileWaistCircumference, profileHipCircumference)" + "values" + "(?,?,?,?,?)";
Connection myConnection = DriverManager.getConnection("jdbc:derby://localhost:1527/stayfitDB2", "username", "password");
Statement myStatement = myConnection.createStatement();
//Statement myStatement2 = myConnection.createStatement();
PreparedStatement prepared = myConnection.prepareStatement(query);
prepared.setString(1, profileName);
prepared.setString(2, profileGender);
PreparedStatement prepared2 = myConnection.prepareStatement(query2);
prepared2.setDouble(1, profileAge);
prepared2.setDouble(2, profileWeight);
prepared2.setDouble(3, profileHeight);
prepared2.setDouble(4, profileWaistCircumference);
prepared2.setDouble(5, profileHipCircumference);
int rowsAffected = prepared.executeUpdate();
int rowsAffected2 = prepared2.executeUpdate();
if(rowsAffected==0)
{
System.out.println("Warning: User data did not save!");
}
else
{
System.out.println("User info saved!");
}
}
catch(SQLException e)
{
System.out.println("Error: "+e.toString());
}
Your save() method will attempt to add the user to the stayfitapp.userprofile table. This table has a field called profileName. profileName is the "primary key" so no duplicate values are allowed.
The error that you are getting is saying that you cannot add(insert) the record to the table because the table already has a record with the same name.
Does your program work okay if you use a different name each time?
You will need to add some logic to your program to deal with the scenario where the profileName already exists in the table. This will probably involve deleting or updating the existing record.
This is the problem.
insert into stayfitapp.userprofile"
+ "(profileName, profileGender)" + "values" , etc
You have nothing to check to see if a record already exists. Something like this would work better.
insert into stayfitapp.userprofile
profileName, profileGender
select distinct ?, ?
from someSmallTable
where not exists (
select 1
from stayfitapp.userprofile
where profileName = ?
)
The someSmallTable bit depends on your database engine, which you didn't specify.
I ended up writing a method to check if the username was already in the profile table. If the username was a duplicate I only wrote to the data table. If the username was new I wrote to both tables.
Thank you for your help! I'm sure there was a more efficient method (figuratively and literally) but I'm on to my final project and nearly surviving an actual CS class.

MYSQL LAST_INSERT_ID not working as intended. How do I fix?

I wrote MySQL StoredProcedure to create and return new ID for each table value, however, it gets wrong value on last_insert_id() from MySQL WorkBench and Java application.
This procedure will be called from multiple sessions.
CALL `GET_NEW_ID`('test', #test);
select #test;
It gives me "141215000000" and this means last_insert_id() returns 0 all the time.
I see it correctly inserts new data into seq_data as supposed though.
CREATE PROCEDURE `GET_NEW_ID`(IN V_TABLE VARCHAR(10), OUT V_ID VARCHAR(12))
BEGIN
INSERT INTO seq_data ( id, `name`, `stat_date`)
SELECT IFNULL(MAX(id), 0)+1, V_TABLE, DATE_FORMAT(NOW(),'%Y%m%d') FROM seq_data WHERE name = V_TABLE AND stat_date = DATE_FORMAT(NOW(),'%Y%m%d');
SET V_ID = concat(DATE_FORMAT(NOW(),'%y%m%d'),LPAD(LAST_INSERT_ID(), 6, '0'));
END
Table looks like this.
CREATE TABLE `seq_data` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`name` varchar(20) COLLATE utf8_bin NOT NULL,
`stat_date` varchar(8) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`,`name`,`stat_date`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
My goal is like...
CALL `GET_NEW_ID`('test', #test);
select #test;
return 141215000001
CALL `GET_NEW_ID`('test', #test);
select #test;
return 141215000002
CALL `GET_NEW_ID`('hello', #test);
select #test;
return 141215000001
As stated in the MySQL documentation, LAST_INSERT_ID() returns a BIGINT (64-bit) value representing the first automatically generated value that was set for an AUTO_INCREMENT column by the most recently executed INSERT statement to affect such a column.
In your case, you are inserting the id, so an AUTO_INCREMENT value is not generated, thus LAST_INSERT_ID returns 0.
You may try something like:
CREATE PROCEDURE `GET_NEW_ID`(IN V_TABLE VARCHAR(10), OUT V_ID VARCHAR(12))
BEGIN
INSERT INTO seq_data (`name`, `stat_date`)
SELECT V_TABLE, DATE_FORMAT(NOW(),'%Y%m%d') FROM seq_data WHERE name = V_TABLE AND stat_date = DATE_FORMAT(NOW(),'%Y%m%d');
SET V_ID = concat(DATE_FORMAT(NOW(),'%y%m%d'),LPAD(LAST_INSERT_ID(), 6, '0'));
END

Selecting value from SQL sever using exists

Hai all I am currently doing a project for a hospital clinical lab. I have come across a problem while fetching data from database. The problem is as follows.
I have 2 category of tests namely Single test and Profile test. The master table of tests contain both the category of tests.
MASTER TABLE of TESTS(LAB_TEST_SERVICES)
CREATE TABLE LAB_TEST_SERVICES (inttestid bigint identity NOT NULL IDENTITY,
testid varchar(15) NOT NULL, testname varchar(255) NOT NULL, cptdesc varchar(300),
splinstr varchar(300), tstabbr varchar(25), reordertime numeric(15),
tstduration numeric(15), autocancel numeric(15), minbiltime numeric(15),
status int NOT NULL, maxbiltime numeric(15), PRIMARY KEY (inttestid));
The type and category of test is stored in following table
LAB_SERVICES_TYPE
CREATE TABLE LAB_SERVICES_TYPE (inttypeid bigint identity NOT NULL IDENTITY,
inttestid bigint NOT NULL, testtype varchar(25), visitype int NOT NULL,
appgendr char(2) NOT NULL, PRIMARY KEY (inttypeid));
If the test comes under single test category, I need to fill the details to the columns of following tables namely LAB_SPECIMEN_MAPPING,LAB_PARAMETER_MAPPING and LAB_TEST_LOCATION.
LAB_SPECIMEN_MAPPING
CREATE TABLE LAB_SPECIMEN_MAPPING (inttestspcid bigint identity NOT NULL IDENTITY,
inttestid bigint NOT NULL, intspcid bigint NOT NULL, intcontid bigint NOT NULL,
volcol numeric(15, 3) NOT NULL, volreq numeric(15, 3) NOT NULL,
status int NOT NULL, PRIMARY KEY (inttestspcid));
LAB_PARAMETER_MAPPING
CREATE TABLE LAB_PARAMETER_MAPPING (intparaid bigint identity NOT NULL IDENTITY,
inttestid bigint NOT NULL, paraname varchar(255) NOT NULL,
parseq numeric(15, 3) NOT NULL, resulttype varchar(30), shortname varchar(30),
mand int NOT NULL, derived int NOT NULL, status int NOT NULL,
PRIMARY KEY (intparaid));
LAB_TEST_LOCATION
CREATE TABLE LAB_TEST_LOCATION (intlocid bigint identity NOT NULL IDENTITY,
intlabid bigint NOT NULL, inttestid bigint NOT NULL, status int NOT NULL,
PRIMARY KEY (intlocid));
And if the test comes under Profile Test category then I need to fill the details to the columns of following table namely LAB_PROFILE_TEST_LIST. Here for each profile test I am mapping a single test to it.
LAB_PROFILE_TEST_LIST
CREATE TABLE LAB_PROFILE_TEST_LIST (intproftestid int identity NOT NULL IDENTITY,
intprotestid int NOT NULL, intsintestid int NOT NULL, PRIMARY KEY (intproftestid));
I had done the following code to find the name of test which is mapped ie for single test if it is mapped then the testid(inttestid from LAB_TEST_SERVICES) will be inserted in LAB_SPECIMEN_MAPPING,LAB_PARAMETER_MAPPING and LAB_TEST_LOCATION or if the test is profile test the testid(inttestid from LAB_TEST_SERVICES) will be inserted in LAB_PROFILE_TEST_LIST.
The tests which is mapped ( both single & profile test).(My contribution to my problem).
SELECT *
FROM LAB_TEST_SERVICES lts
WHERE EXISTS
(SELECT lsm.inttestid
FROM LAB_SPECIMEN_MAPPING lsm
WHERE lsm.status = 1
AND lts.inttestid = lsm.inttestid)
AND EXISTS
(SELECT ltl.inttestid
FROM LAB_TEST_LOCATION ltl
WHERE ltl.status = 1
AND lts.inttestid = ltl.inttestid)
AND EXISTS
(SELECT lptr.intprotestid
FROM LAB_PROFILE_TEST_LIST lptr WHERE lts.inttestid = lptr.intprotestid)
So when I tried to do this no tests appear because I know that there will be no tests having both the characteristics of Single and Profile tests. I had done so many things but cant find a solution. Kindly help me to find out the details tests which is mapped both single and profile.I am using Java, Hibernate and SQL SERVER. Thanks in advance

Best way to initialize objects when using a dao

I'm building a Tomcat app using MySQL. I'm using a DAO pattern to talk to the database. I'm having trouble with where to initialize fields within the objects.
Mostly to save typing... I am using EclipseLink JPA to Generate model Entities from Tables. I am writing the DAO code by hand. I was writing the model by hand but this seemed easier.
The problem I am having is with writing the object back to the database will all the default nulls. For example, this table contains a bunch of id columns. Not all of them have context for every instance of the object. It seems inefficient to create the object and have to set all the fields to zero in order to be ale to save them to the database. If they have not context, I'd like to just leave them alone. i.e. I only want to set the fields that have context for what I am doing at that moment.
It seems best to use use the constructor in the model class to initialize them. But if I do that, EclipseLink will overwrite them the next time I generate the model.
Having the DAO update method check for nulls and set them to zero seems like a kludge. I suppose I could also use a factory to create and initialize the model class.
But I wonder if I am over thinking this... Any of these solutions would work. But there must be an accepted pattern for this.
How should I approach it?
Thanks
Model is just getters and setters. Contructor is empty.
Excerpts of code are below...
Notice notice = new Notice();
notice.setEvent("Welcome");
notice.setUserid(user.getId());
noticeDao.updateNotice(notice);
DAO:
//this seems inefficient
if(notice.getTravid() == null) notice.setTravid(0L);
if(notice.getBusid() == null) notice.setBusid(0L);
if(notice.getSaveid() == null) notice.setSaveid(0L);
if(notice.getTargid() == null) notice.setTargid(0L);
if(notice.getTestmode() == null) notice.setTestmode(false);
String SQLupdate = "UPDATE notices SET "
+ "userid = ?, "
+ "travid = ?, "
+ "busid = ?, "
+ "saveid = ?, "
+ "targid = ?, "
+ "testmode = ?, "
+ "event = ?, "
+ "status = ?, "
+ "error = ?, "
+ "created = ?, "
+ "modified = ?, "
+ "log = ? "
+ "WHERE id = ?";
ps = conn.prepareStatement(SQLupdate);
ps.setLong(1, notice.getUserid());
ps.setLong(2, notice.getTravid());
ps.setLong(3, notice.getBusid());
ps.setLong(4, notice.getSaveid());
ps.setLong(5, notice.getTargid());
ps.setBoolean(6, notice.getTestmode());
ps.setString( 7, notice.getEvent());
ps.setString( 8, notice.getStatus());
ps.setString( 9, notice.getError());
ps.setObject(10, notice.getCreated());
ps.setObject(11, notice.getModified());
ps.setString(12, notice.getLog());
ps.setLong( 13, notice.getId());
ps.executeUpdate();
DB:
CREATE TABLE `notices` (
`id` int(20) unsigned NOT NULL AUTO_INCREMENT,
`userid` int(20) unsigned NOT NULL DEFAULT '0',
`travid` int(20) unsigned NOT NULL DEFAULT '0',
`busid` int(20) unsigned NOT NULL DEFAULT '0',
`saveid` int(20) unsigned NOT NULL DEFAULT '0',
`targid` int(20) unsigned NOT NULL DEFAULT '0',
`testmode` tinyint(1) DEFAULT '0',
`event` varchar(40) DEFAULT NULL,
`status` varchar(20) DEFAULT 'Pending',
`error` varchar(255) DEFAULT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
`log` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8
The database table is like this:
ID
Generically, the code looks like this:
Just to address your specific question, isn't there a way to tell eclipselink to set default values of the fields?
But there may be a deeper problem, with your database design. Are the *id fields not foreign key? They should be. And if they are foreign keys, then their value in database should be null, not 0L for rows where the specific fields do not have context.
At even deeper lever, if most of them don't have context in most rows -- that is, not being in context is an exception rather then norm -- then perhaps your database design itself is not good. You might be designing a universal table and will benefit from breaking the single table into multiple.
Thanks for the great input. The solution I settled on was just to use the generic setObject for all data types. i.e.
ps.setLong(1, notice.getUserid());
becomes
ps.setObject(1, notice.getUserid());
MySQL seems perfectly happy with that. NULLs are not a problem. And it's a lot less work.

Categories

Resources