Populate SQL table column from another table - java

I have a jqGrid(latest free jqGrid version) table filled with data from the database(MS SQL) using a Java REST service. One of the jqGrid columns its a drop down list with 6 options.
My asignment is to create another database table that contains the Drop Down List values and using foreign keys / primary keys i have to automaticly populate the first table DDL values.
I am failing to understand the logic behind it. Can someone expain this to me? How can i achieve this. Do i only send a ID from jqGrid and depending on that ID(1,2,..,6) it chooses what to set in table#1 DDL column(comparing the id sent with the ID's of the table that contains the DDL Values)?
I am getting the feeling i am not expressing myself well... Hope you guys understand me.

We can start with the database table. It could look like
CREATE TABLE dbo.OrderStatus (
Id int IDENTITY NOT NULL,
Name nvarchar(100) NOT NULL,
CONSTRAINT PK_LT_OrderStatus PRIMARY KEY CLUSTERED (Id),
CONSTRAINT UC_LT_OrderStatus_Name UNIQUE NONCLUSTERED (Name)
)
It allows to address any Item of such OrderStatus table by Id or by Name. The UNIQUE CONSTRAINT don't permit to add name duplicates. Another table Order can have column
CREATE TABLE dbo.Order (
Id int IDENTITY NOT NULL,
OrderStatusId int NOT NULL,
...
)
ALTER TABLE dbo.Order WITH CHECK ADD CONSTRAINT FK_Order_OrderStatus
FOREIGN KEY(OrderStatusId) REFERENCES dbo.OrderStatus (Id)
During filling the grid with the data you have two main options: using OrderStatusId in the data or the usage of the corresponding Name from dbo.OrderStatus:
SELECT Id,OrderStatusId, ... FROM dbo.Order
or
SELECT Id,os.Name AS OrderStatus, ...
FROM dbo.Order AS o
INNER JOIN dbo.OrderStatus AS os ON os.Id=o.OrderStatusId
If you decide to fill the grid with ids (OrderStatusId values) then you will have to use formatter: "select" to display the text in the corresponding column (see here). It required that you would have to have editoptions.value filled with all different values from dbo.OrderStatus. The best way to implement this would be to extend the response from the server for filling the grid with your custom data and to use beforeProcessing to set editoptions.value. I described the scenario in the answer. I'll remind you it below.
Let us the response from the server looks like
{
"rows": [{...}, {...}]
}
If the returned data looks just like
[{...}, {...}]
then you should include the wrapping. I suggest that you made
SELECT Id,Name FROM dbo.OrderStatus
additionally to making the main select from dbo.Order (SELECT * FROM dbo.Order) and you place both results in the server response:
{
"orderStatus": [{"id":1, "name":"Pending"}, ...],
"rows": [{...}, {...}]
}
To process orderStatus you need to add the following beforeProcessing, which read orderStatus and set editoptions.value of the orderStatus column of the grid:
beforeProcessing: function (response) {
var $self = $(this), orderStatus = response.orderStatus, i, values = "";
if (orderStatus != null && orderStatus.length > 0) {
for (i = 0; i < orderStatus.length; i++) {
if (values.length > 0) {
values += ";";
}
values += orderStatus[i].id + ":" + orderStatus[i].name;
}
$self.jqGrid("setColProp", "orderStatus", {
editoptions {
value: values
}
});
if (this.ftoolbar) { // filter toolbar exist
$self.jqGrid("destroyFilterToolbar");
$self.jqGrid("filterToolbar");
}
}
}
The above code is not tested, but I hope that the main idea should be clear from it.

Related

Problem with integrity constraint in hibernate (JpaRepository) when updating a register

I have two tables in a database, A and B. Defined in the following way:
CREATE TABLE A (
id NUMBER,
Name VARCHAR(100),
CONSTRAINT pk_id PRIMARY KEY (id)
);
CREATE TABLE B (
id NUMBER,
a_id NUMBER,
CONSTRAINT pk_id PRIMARY KEY (id),
CONSTRAINT id_a_id FOREIGN KEY (a_id) REFERENCES a(id)
);
What I want to do is using JpaRepository update a register "lets suppose with id:5" of the A table when the B table have a register with a_id:5.
To do that, the first think y tried is to get the entity from the A database, modify the Name value, delete the old register and save a new one with the changes:
#Transactional
void update()
{
List<A> oldARegisterList = a.findById(5);
A oldARegister = oldARegisterList.get(0);
A newRegister = new A(oldARegister);
a.delete(oldARegister);
newRegister.setName("NewName");
a.save(newRegister);
}
But I was getting a ORA-02291: integrity constraint (id_a_id) violated - parent key not found.
Then I have tried to delete the register in B, delete and create the register in A with the new name and finally create again the register in B:
#Transactional
void update()
{
List<A> oldARegisterList = a.findById(5);
A oldARegister = oldARegisterList.get(0);
B oldBRegister = oldARegister.getB();
b.delete(oldBRegister);
A newRegister = new A(oldARegister);
a.delete(oldARegister);
newRegister.setName("NewName");
a.save(newRegister);
b.save(oldBRegister);
}
An it dosen't work ether giving the same problem, but if I execute manally first the deletion of B register, then the update of the A register and finaly the recreation of the B register it works.
So it seems that if the process of delete B update A and recreate B is in the same transaction, the process does not work.
How it is possible to do that in the same transaction?
Thank you very much.
As a first note I should notice that you can simple update oldARegister name without deleting oldBRegister because name is not primary key on A so just use this:
oldARegister.setName("New Name");
a.save(oldARegister);
But if you want to do it on your way, you should set A of oldBRegister to newRegister like this:
oldBRegister.setA(newRegister)
b.save(oldBRegister);

PostgreSQL/Derby/Hibernate Insert Trigger - Retrieving inserted record, foreign key is always null

I've got tree structure entity named Category with children field.
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "parent_id")
#OrderColumn
#JsonProperty("children")
private List<Category> children = new LinkedList<Category>();
In database it looks like this:
I've got also lineage field helpful to list tree. (look here : https://stackoverflow.com/a/6277217) .
#JsonIgnore
#Column(name = "LINEAGE")
private String lineAge = new String("/");
After category creation i want append to that lineage parentId of inserted category. I created after insert trigger for that, but foreign key (PARENT_ID) of inserted row is always null in context of trigger.
create trigger add_category_lineage
after insert on CATEGORY
referencing new as insertedrow
for each row
update CATEGORY set LINEAGE = LINEAGE || TRIM(CAST((insertedrow.PARENT_ID AS CHAR(10)))) || '/' where ID = insertedrow.ID and insertedrow.PARENT_ID is not null
I am using 10.11.1.1 derby. Why foreign key in inserted row (in trigger context only) is always null, it works for any other field for example name. Maybe instead of use after insert trigger to append parent id to lineage field can i do this from hibernate level ?
EDIT 1.
I tested this example with postgreSQL 9.4 and the result is the same.
CREATE OR REPLACE FUNCTION after_insert_category_trigger_function()
RETURNS trigger AS '
BEGIN
UPDATE category set lineage = lineage || new.parent_id::text || ''/'' where id = new.id;
RETURN NEW;
END' LANGUAGE 'plpgsql';
CREATE TRIGGER after_insert_category_trigger
AFTER INSERT ON category
FOR EACH ROW
EXECUTE PROCEDURE after_insert_category_trigger_function();
The result after entity creation (id = 25). Like you can see it works well with name field (id = 23) :
It doesn't work with before insert trigger also:
CREATE OR REPLACE FUNCTION after_insert_category_trigger_function()
RETURNS trigger AS '
BEGIN
NEW.LINEAGE := NEW.LINEAGE || new.parent_id::text || ''/'';
RETURN NEW;
END' LANGUAGE 'plpgsql';
CREATE TRIGGER after_insert_category_trigger
BEFORE INSERT ON category
FOR EACH ROW
EXECUTE PROCEDURE after_insert_category_trigger_function();

Id of entity is different after hibernate save from oracle database with sequence autogeneration id

Entity with id autogenerated from oracle trigger sequence.
#Entity
#Table(name = "REPORT", schema = "WEBPORTAL")
public class Report {
private Integer id;
....
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="report_sequence")
#SequenceGenerator(name="report_sequence", sequenceName = "report_id_seq")
#Column(name="REPORT_ID", unique = true, nullable = false)
public Integer getId() {
return id;
}
....
}
Service
#Service("reportService")
public class ReportServiceImpl implements ReportService {
....
#Transactional(readOnly=false)
public void saveOrUpdate(Report report) {
reportDAO.saveOrUpdate(report);
}
}
DAO
#Repository
public class ReportDAOImpl implements ReportDAO {
....
#Override
public Report save(Report report) {
try {
Session session = sessionFactory.getCurrentSession();
session.save(report);
} catch (Exception e) {
logger.error("error", e);
}
return report;
}
}
And When I call service's saveOrUpdate and then try to reach id of entity I get different value than persisted in database. Values on database with autogeneration all is ok. Any suggestions?
reportService.saveOrUpdate(report);
System.out.println(report.getId());
prints: 4150
but saved id in database is: 84
NOTE: My purpose to get Id comes from that I wanted to save childs with cascade. But foreign key on child was different in database(the values of id that I get with getId()).
And Id generated in database is incremented by 2. EX: 80, 82, 84.
UPDATE:
Oracle trigger for sequence generation
CREATE OR REPLACE TRIGGER REPORT_ID_TRIG
BEFORE INSERT ON WEBPORTAL.REPORT
FOR EACH ROW
BEGIN
SELECT report_id_seq.NEXTVAL
INTO :new.report_id
FROM dual;
END;
ANSWER: Trigger should check if id is null
CREATE OR REPLACE TRIGGER REPORT_ID_TRIG
BEFORE INSERT ON WEBPORTAL.REPORT
FOR EACH ROW
WHEN (new.report_id is null)
BEGIN
SELECT report_id_seq.NEXTVAL
INTO :new.report_id
FROM dual;
END;
DESCRIPTION:
#GeneratedValue is not just a sequence generator. It's bit of HiLo algorithm.When it first requests id from database it multiplies it with 50(it can differ) and next 50 new entities will be given ids consequently, and than next request to database. This is to decrease request to database.
The numbers that I get from java was right numbers that should be saved on report.
Without id null value check Hibernate firstly requested for id from database and sequence.nextval called. When hibernate was persisting it(completing transaction) the database called sequence.next second time and set that value to database. So on ReportDetails there was true id value of report and on the Report id it was id set from database.
The problem is that two separate mechanisms are in place to generate the key:
one at Hibernate level which is to call a sequence and use the value to populate an Id column and send it to the database as the insert key
and another mechanism at the database that Hibernate does not know about: the column is incremented via a trigger.
Hibernate thinks that the insert was made with the value of the sequence, but in the database something else occurred. The simplest solution would probably be to remove the trigger mechanism, and let Hibernate populate the key based on the sequence only.
Another Solution:
check your trigger definition that should be in this format
(WHEN (new.report_id is null) ) is important.
CREATE OR REPLACE TRIGGER TRIGGER_NAME
BEFORE INSERT ON TABLE_NAME
FOR EACH ROW
WHEN (new.id is null)
BEGIN
SELECT SEQUENCE_NAME.NEXTVAL
INTO :new.id
FROM dual;
END

How to persist entity object retrieved from a JTable through JPA?

I have been trying for days to persists data obtained from a jtable from an imported Excel sheet without success and trying to find the exception is sickening.
here is some part of the code and the error stack trace
#Action
public void persist(){
emf = Persistence.createEntityManagerFactory("MauranaSurveyPU");
em = emf.createEntityManager();
em.getTransaction().begin();
//loops through table to retrieve object and persist
int count = jTable1.getRowCount();
for(int i=0; i<count; i++){
Mauranagroup mn = new Mauranagroup();
String obj1 = (String)GetData(jTable1,i,0);
String obj2 = (String)GetData(jTable1,i,1);
String obj3 = (String)GetData(jTable1,i,2);
//set entity
mn.setRespondentId(Integer.parseInt(obj1));
mn.setMale(obj2);
mn.setFemale(obj3);
em.persist(mn);
}//end for
em.getTransaction().commit();
}//end method persist
// get object from jtable
private Object GetData(JTable jTable1, int x, int y) {
return jTable1.getModel().getValueAt(x,y);
}
The problem with this code is that it actually persists ,but after the transaction commits
i get this stack trace;
Internal Exception: 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 'SQL130204062549290' defined on 'MAURANAGROUP'.
Error Code: 20000
Call: INSERT INTO MAURANAGROUP (RESPONDENT_ID, AMOUNTTOBESPENT, AREYOUFAMILIARNO
bind => [211 parameters bound]
Query: InsertObjectQuery(entity.Mauranagroup[ respondentId=5 ])
when i delete the records and persist again, i get another line
bind => [211 parameters bound]
Query: InsertObjectQuery(entity.Mauranagroup[ respondentId=2 ])
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
i dont understand is it,it actually persist and i can see my saved data. is it the loop or is the loop not terminating well,im actually sick because of this project.
There is a DB constraint on your table that some column is unique and you are inserting the duplicate value. I guess it is the RESPONDENT_ID. If you are trying to persist all the record in the table for the first time, I wouldn't provide the id from the table data. Instead I would use sequence to generate the id for you and return it to the UI.
If you are trying to modify the existing data stored in the table. I would search them in the DB using the id, update the fields and persist them again.
btw. it is a good practice to name your methods with lowercase at the beginning.

Select a group of records at a time based on them having same value in a particular column

I want to be able to use a single query to select all records out of a table having the same value in a particular column.
Clarification
Conditions:
- document_id is not a primary key.
List ids = SELECT DISTINCT T.document_id FROM table T;
List block = SELECT * from table where document_id = ids.next();
perform operation on the block, then retrieve next block
Could anyone please tell me how to convert these two queries into a single query?
UPDATE
#Marco #StephanB really sorry that my question was so vauge...i should learn to be more specific...
anyway, i am using JAVA and Apache Turbine with Torque.
Here's the code which i want to change:
public void runQueue (String username, Customer customer) {
Criteria c = new Criteria();
c.add( DataEntryQueuePeer.CUSTOMER_ID, customer.getId());//DataEntryQueue.CUSTOMER_ID is not the primary key
c.add( DataEntryQueuePeer.STATUS, DataEntryQueue.STATUS_IN_KEYING );
c.add( DataEntryQueuePeer.DATA_ENTRY_USERID, username );
c.add( DataEntryQueuePeer.QUEUE_TYPE, Constants.CUSTOMER_QUEUE );
List<DataEntryQueue> v = DataEntryQueuePeer.doSelect( c );
if( v.size() > 0 ) {
//do something with v
v.setStatus(DataEntryQueue.STATUS_KEYING_COMPLETE);
v.setModified(true);
v.save();
}
}
I want to add one more field(DataEntryQueuePeer.DOCUMENT_ID) in the criteria so that only records with the same document_id are selected on every "doSelect". No specific DOCUMENT_ID is passed to the method though.
please let me know if i'm still not clear enough...thanks.
Your SQL is malformed. A correct question is more likely to retrieve a correct answer. I'll name your table A and B.
SELECT * FROM B WHERE B.document_id IN (SELECT DISTINCT A.document_id FROM A)

Categories

Resources