Cannot insert object to HSQLDB with ActiveJDBC - java

I'm trying to use ActiveJDBC with HSQLDB:
Users.sql
CREATE TABLE users (
"ID" INTEGER GENERATED BY DEFAULT AS SEQUENCE seq NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100) NOT NULL,
LAST_NAME VARCHAR(100) NOT NULL
);
User.java
#IdName("ID")
public class User extends Model {....}
Main.java
User u = new User();
u.setFirstName("first_name");
u.setLastName("last_name");
u.save();
And when I try to save new row I have the following exception:
org.javalite.activejdbc.DBException: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: id, Query: INSERT INTO users (first_name, last_name) VALUES (?, ?), params: first_name,last_name
I think that problem in lower case in insert query. How I can fix this problem?

After googling for this HSQL exception message, I threw this code together that actually works. It uses ActiveJDBC, works with plain query and also works with instrumented model:
Base.open("org.hsqldb.jdbc.JDBCDriver", "jdbc:hsqldb:file:./target/tmp/hsql-test", "sa", "");
String create = "CREATE TABLE people (\n" +
" ID INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL,\n" +
" FIRST_NAME VARCHAR(100) NOT NULL,\n" +
" LAST_NAME VARCHAR(100) NOT NULL\n" +
");";
Base.exec(create);
Base.exec("INSERT INTO people (first_name, last_name) VALUES (?, ?)", "John", "Doe");
System.out.println("===>" + Base.findAll("select * from people"));
Person p = new Person();
p.set("first_name", "Jane", "last_name", "Doe").saveIt();
System.out.println(Base.findAll("select * from people"));
System.out.println(Person.findAll());
Base.close();
As you can see, the code that creates a table is a bit different, especially around the ID column.
The model looks like this:
#IdName("ID")
public class Person extends Model {}
Basically, you had the following issues with your code:
Definition of ID column with double quotes
ID column needs to be defined as IDENTITY (do not hold my feet to the fire, I'm no HSQL expert, but t works)
The model needs to overwrite the #IdName("ID"), since ActiveJDBC defaults to lower case id, unless you change that in the table (why not?)
Keep in mind, that some things may not work, since HSQL is not on a list of supported databases.
I hope this helps!

CREATE TABLE users (
ID INTEGER GENERATED BY DEFAULT AS SEQUENCE seq NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100) NOT NULL,
LAST_NAME VARCHAR(100) NOT NULL
);

Related

How to join values from another table with hibernate jpa?

I have a products table that contains especially a product_name and a product_type.
For certain product types, I'd like to create some kind of overlay mapping table that replaces the value in product_name.
In pure mysql, I would solve this as follows:
CREATE TABLE products (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
product_price;
product_quantity;
...
)
#Entity
public class Product {
long id;
String product_type;
String product_name;
String product_price;
...
}
CREATE TABLE product_mapping (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
PRIMARY KEY (id)
);
My goal: if product_mapping contains the product_type, override the product_name. Else, stick to the value in products.product_name table.
SELECT ..., ifnull(product_mapping.product_name, products.product_name) AS product_name
FROM products
LEFT JOIN product_mapping ON products.product_type = product_mapping.product_type;
But how could I create the same mapping with a hibernate #Entity
Sidenote: A #Formula creates an additional SELECT for each query, whose result is merged into the #Entity. I'm looking for a JOIN!

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.

How to get a specific "row" from a DB using JPA (EclipseLink) when the primary key is Auto Incremented?

Say I have this table
CREATE TABLE person(
person_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
x_cordinates INT,
y_cordinates INT
);
In the past I have used
Person person = EntityManager.find(Person.class, primaryKey);
But the primary key in this instance is auto incremented, is it possible to get a row back using the other colums such as first_name and last_name to get the primary key along with the other values ?
You can create a NamedQuerry like that :
#NamedQuery(name="person.findAll", query="SELECT p FROM Person p WHERE like :first_name")
And can assign a value to "first_name" like that :
query.setParamter("fist_name", "%name%");
You can read this documentation.
Use method createQuery or createNativeQuery of entityManager.
With createQuery you have to use JPQL syntax and with createNativeQuery, you've to use the standard SQL syntax.
For example :
Query query = EntityManager.createQuery("select * from person p where p.first_name = :fname");
17.
query.setParameter("fname", firstName);
Person p = query.getSingleResult();

unique constraint violated?

i'm trying to update a table:
create table Out_Patient(Patient_ID number(8) primary key ,
First_Name varchar2(20) ,
Last_Name varchar2(20) ,
Gender varchar2(10) ,
Mobile_Number number(12) ,
Address varchar2(20),
Date_Of_Birth Date ,
Date_Of_Entry Date)
with foll. code:
PreparedStatement st= con.prepareStatement("Update Out_Patient Set Patient_ID=?,First_Name=?,Last_Name=?,Gender=?,Mobile_Number=?,Address=?,Date_Of_Birth=?,Date_Of_Entry=?");
String t1=text1.getText();
int id=Integer.parseInt(t1);
String t2=text2.getText();
String t3=text3.getText();
String t4=text4.getText();
String t5=text5.getText();
String t6=text_dob.getText();
String t7=text_doe.getText();
String s1=combo_gender.getSelectedItem().toString();
st.setInt(1,Integer.parseInt(t1));
st.setString(2,t2);
st.setString(3,t3);
st.setString(4,s1);
st.setString(5,t5);
st.setString(6,t4);
st.setString(7,t6);
st.setString(8,t7);
st.executeUpdate();
But i'm getting ORA-00001: unique constraint violated.
I know Patient_ID is primary key in table,but while entering details i'm keeping it same as the one in the table.What changes should be made.
Please help!!
Thanks..
Theres no WHERE clause in your JDBC update statement, therefore you're trying to set the same ID for all records. Take a look at this example: Creating a PreparedStatement Object

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