Hibernate + oracle sequence + trigger - oracle

I have a table with an index auto filled by a trigger that use a sequence (Oracle database)
CREATE TABLE A
(
IDS NUMBER(10) NOT NULL
)
CREATE OR REPLACE TRIGGER A_TRG
BEFORE INSERT
ON A REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
:new.IDS := A_SEQ.nextval;
END A_TRG;
/
I have a matching Java class:
Class A {
#Id
#SequenceGenerator(name = "aSequence", sequenceName = "A_SEQ", allocationSize = 1)
#GeneratedValue(generator = "aSequence", strategy = GenerationType.SEQUENCE)
#Column(name = "IDS")
Long id;
...
}
When I try to persist an instance of A like this:
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
A a = new A();
Long id = getHibernateTemplate().save(a);
transaction.commit();
I get this problem:
ID in code returned by the save call = "X"
ID in database = "X+1"
Is there a way to setup Hibernate to let the database trigger create the ID ?
Thanks

Reponse found at HIbernate issue with Oracle Trigger for generating id from a sequence
I need to adapt my trigger to run only if no ID is given:
CREATE OR REPLACE TRIGGER A_TRG
BEFORE INSERT
ON A REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
WHEN (New.IDS is null) -- (1)
BEGIN
:new.IDS := A_SEQ.nextval;
END A_TRG;
/
(1) this line allow Hibernate to manually call A_SEQ.nextVal to set the ID and then bypass the trigger else Hibernate will get the nextval for uselessly because the trigger will always reset the ID calling nextval again

In your class B you have #GeneratedValue(generator = "preferenceSequence") which not defined in the example that you have, it should be #GeneratedValue(generator = "bSequence")
By default hibernate allocation size is 50 the B: IDS=50 seems to suggest the mapping is picking the wrong sequence.

Related

Add extra condition to jointable in springboot

I have 2 tables which are related using a mapping table i.e FK of these tables are stored in a mapping table (Joining table).
Users {
uid,
uname
}
Dept {
deptid,
dept_name
}
User_Dept{
ud_id,
uid
deptid
status
}
So in my User Entity i have ManytoOne relation with Dept Entity and have added #Jointable annotation to joining table ( User_Dept) like below
User.java
````#ManyToOne
````#JoinTable(
````name="UserDept",
````joinColumns = ````{#JoinColumn(name="uid",referencedColumnName="uid")},
```` inverseJoinColumns = {#JoinColumn(name="deptid", ````referencedColumnName="deptid")}
````)
````private Dept dept;
}
All good!!
But i have a business scenario to fetch only those users belonging to a particular Dept and who are 'active'.
Basically i need to add extra condition to my #jointable(user_dept) to fetch those users whose "status=active" from user_dept table.
I have tried adding #WhereJoinTable(clause = "status=active") like below
class User {
````#JoinTable(
```` name="UserDept",
````joinColumns = ````{#JoinColumn(name="uid",referencedColumnName="uid")},
```` inverseJoinColumns = {#JoinColumn(name="deptid", ````referencedColumnName="deptid")}
````)
````#WhereJoinTable(clause = "status=active")
````}
And also #where(clause = "status=active") at class level.Nothing works.
Issue:
1. where annotation adds a condition to the base query on User table instead of user_dept table.
2. wherejointable annotation- doesnt seem to have any impact.
3. Tried adding #where on userdept class (based on point 1) , but no luck.
Can someone help?
Also if you can propose any alternate solution even thatworks

Getting ORA-00001 unique constraint violated error when calling a trigger

create or replace TRIGGER "DB"."TRIG_PERIOD_TRUANCY_INS_UPD"
AFTER UPDATE OR INSERT
ON AT_PERIOD_ATTENDANCE_RECORDS
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
IF UPDATING THEN
delete at_period_truancy where period_attendance_records_id = :old.period_attendance_records_id;
END IF;
insert into at_period_truancy (period_attendance_records_id, district_number, school_id, student_id, calendar_date, school_year, minutes)
select :new.period_attendance_records_id, :new.district_number, :new.school_id, :new.student_id, :new.calendar_date, :new.school_year,
(case when :new.attendance_status = 'A' then period.end_time - period.begin_time
when coalesce(:new.tardy_time_in_time, period.begin_time) - period.begin_time >
period.end_time - coalesce(:new.tardy_time_out_time, period.end_time)
then coalesce(:new.tardy_time_in_time, period.begin_time) - period.begin_time
else period.end_time - coalesce(:new.tardy_time_out_time, period.end_time) end)*24*60
from ca_calendar cal
inner join ca_school_calendar calendar
on (cal.district_number = calendar.district_number
and cal.calendar_id = calendar.calendar_id )
inner join sc_class_meeting_pattern meeting
on (calendar.cycle_day_cd = meeting.cycle_day_cd)
inner join sc_class class
on (class.school_scheduling_param_id = meeting.school_scheduling_param_id
and class.class_id = meeting.class_id)
inner join sc_period_info period
on (meeting.school_scheduling_param_id = period.school_scheduling_param_id
and meeting.period = period.period)
where :new.district_number = cal.district_number
and cal.is_active_ind = 1
and :new.school_id = cal.school_id
and :new.school_year = cal.school_year
and :new.calendar_type_cd = cal.calendar_type_cd
and :new.track_number = cal.track_number
and :new.calendar_date = calendar.calendar_date
and :new.school_id = class.school_id
and :new.class_id = class.class_id
and 1 in (select use_in_truancy_report_ind
from enum_at_absence_reason_code
where district_number = :new.district_number
and school_id = :new.school_id
and value = :new.absence_reason_code
union all
select use_in_truancy_report_ind
from enum_at_tardy_reason_code
where district_number = :new.district_number
and school_id = :new.school_id
and value = :new.tardy_reason_code);
END TRIG_PERIOD_TRUANCY_INS_UPD;
This is the trigger that I am using. When calling the update statement this trigger is getting invoked and when I pass tardy_reason_code as UN this error is happening. It executes without any issues if I pass tardy_reason_code with different values.
Trigger is inserting into at_period_truancy tables.
As Oracle raises ORA-00001 (unique constraint violated), it means that you're trying to insert primary key value which already exists in the table.
You didn't post create table statement so it is difficult to guess which columns make the primary key, but - you should know it so check which values you already have in there, compare that to values currently being inserted and you'll know what to do.
Maybe you'll have to modify primary key (add other columns? Abandon idea of current primary key and using a sequence (or identity column)) or the way you're inserting values into the table.

JpaRepository nativeQuery - table does not exists

when trying to perform an update on table using JpaRepository and #Query annotation I receive an error "Table not exists" and:
has thrown exception:org.hibernate.exception.SQLGrammarException: could n
ot execute statement
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute s
tatement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException
: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:261)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
Caused by: oracle.jdbc.OracleDatabaseException: ORA-00942: table or view does not exist
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:498)
... 154 common frames omitted
My Query:
#Modifying
#Transactional
#Query(nativeQuery = true, value = "UPDATE T_MY_TABLE SET VISIBLE_FLAG = 0 "
+ "WHERE ID = :myId ")
int updateMyTab(#Param("myId") Long myId);
When using JpaRepository.save method to update the table, it executes normally without any problems.
Also, I have SELECT nativeQueries, which works. Only the updates does not.
On table there is:
- created synonym for the schema
- grants for select, insert, update, delete for the schema
Table DOES exists, the update, if executed directly on DB and on any schema/user it works without any problems and updates rows
I managed to solve the issue - problem was in database object naming. I used upper-case in object naming while tables names were case sensitive. I had to change:
#Modifying
#Transactional
#Query(nativeQuery = true, value = "UPDATE T_MY_TABLE SET VISIBLE_FLAG = 0 "
+ "WHERE ID = :myId ")
int updateMyTab(#Param("myId") Long myId);
to:
#Modifying
#Transactional
#Query(nativeQuery = true, value = "UPDATE "\t_my_table"\ SET VISIBLE_FLAG = 0 "
+ "WHERE ID = :myId ")
int updateMyTab(#Param("myId") Long myId);

how to update only few columns of a table in spring jdbc template

i am using spring jdbc template and i want to update some of the columns in a table.
Ex:Consider Student table
id-->1007.
name-->Krish.
age-->25.
tel-->0112538956536.
this is a existing record.i want to update some fields only(updating fields change time to time).others should have their existing values.how can i acheive this in Spring JDBC template.Any suggestions will be very much helpful.
Thanks.
you can use jdbc template for update table from application
here is the simple example
String name = "asdads";
int age = 12;
String tel = "+905655465465";
int id = 1;
String SQL = "update Student set name = ?, age= ? ,tel=?, last_updated = sysdate() where id = ?";
jdbcTemplate.update(SQL,name, age, tel, id);
may be just like
jdbcTemplate.update(
"update Student set last_updated=now(),some_field=?",
"some value");

NHibernate, updating a db column to a function call when persisting a domain object

I have a domain class that when persisted to Oracle must update a column to sysdate. NHibernate must only generate 1 SQL. e.g.
update person set age = 12, stamp = sysdate where id = 1;
Can this be done?
EDITED:
Could be something like:
Person person = (Person)session.Get(typeof(Person), 1);
session.SetFunction(person, "stamp", Functions.CurrentTimestamp);
person.Age = 12;
session.Flush();
You could update the stamp via a database trigger:
create trigger person_trg
before update
for each row
begin
:new.stamp := sysdate;
end;
Then all hibernate would need to do is "persist" the change to age (for example).
If you want to do that on demand, you can just execute the query above:
session.CreateQuery("update person set age = 12, stamp = sysdate where id = 1")
.ExecuteUpdate();
Interestingly, that is both valid HQL and SQL.

Resources