JPA createEntityManager causes Oracle 955 error - oracle

I have created a simple JAVA app to learn database connection.
I have table USR_BOOKS in Oracle 11g database. Using EclipseLink(JPA 2.0) Persistence libray.
Using "Create Entity From Database", I created a class in Java, and created JPA Controller class.
Everything seems to work fine except that I always get
[EL Warning]: 2012-10-30 16:50:31.957--ServerSession(1278203495)--Exception
[EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00955: name is already used by an existing object
Error Code: 955
Call: CREATE TABLE USR_BOOKS (ID NUMBER(19) NOT NULL, NAZOV VARCHAR2(255) NULL, PRIMARY KEY (ID))
Query: DataModifyQuery(sql="CREATE TABLE USR_BOOKS (ID NUMBER(19) NOT NULL, NAZOV VARCHAR2(255) NULL, PRIMARY KEY (ID))")
I am not calling the CREATE TABLE query anywhere, but until I call function
EntityManager em = emf.createEntityManager();
the error is not there
It looks like that the function createEntityManager() creates the SQL statement and sends it into database.
I tried deleting the table from database. Then the program creates the table USR_BOOKS in database - again, I am NOT accidentally calling any function that could cause it.
This is basically my code:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JavaOracleDBPU2");
EntityManager em = emf.createEntityManager();
UsrBooksJpaController booksController = new UsrBooksJpaController(emf);
List<UsrBooks> usrBooksAll = booksController.findUsrBooksEntities();
System.out.println(usrBooksAll);
the code works, even prints data from the table, just getting the error

Possibly in persistence.xml eclipselink.ddl-generation property does have value create-tables. Try none instead:
<property name="eclipselink.ddl-generation" value="none"/>

Related

Schema-validation: missing table when upgrading to spring-boot-3 (Hibernate 6 )

Background:
I have upgraded my spring boot project from '2.5.12' to '3.0.0'.
As part of the upgrade hibernate was also updated to 6.1.5.
All the java entities are now using jakarta.persistence instead of javax.persistence
as required
The issue:
When the application starts an error is thrown
Schema-validation: missing table ...
The error is thrown from org.hibernate.tool.schema.internal.AbstractSchemaValidator
The function validateTable meant to validate that the entities match the DB tables.
#Override
protected void validateTables(
Metadata metadata,
DatabaseInformation databaseInformation,
ExecutionOptions options,
ContributableMatcher contributableInclusionFilter,
Dialect dialect, Namespace namespace) {
final NameSpaceTablesInformation tables = databaseInformation.getTablesInformation( namespace );
for ( Table table : namespace.getTables() ) {
if ( options.getSchemaFilter().includeTable( table )
&& table.isPhysicalTable()
&& contributableInclusionFilter.matches( table ) ) {
validateTable(
table,
tables.getTableInformation( table ),
metadata,
options,
dialect
);
}
}
}
Additional info:
The DB tables exist, i can log in and see them.
The databaseInformation.getTablesInformation( namespace ); returns empty results.
The namespace.getTables() shows all the tables correctly.
Hibernate generated classes are created O.K as part of the build (so annotations seem to be working).
Using MySQLDialect
Entities didn't change beside using jakarta.persistence
I don't get any "Connection refused " so connection to the DB is created.
The question:
Any idea what might be the cause?
Is there an issue with the model or reading schema data from the DB?
Might this be an issue of some dependency incompatibility?

Spring Boot Data JDBC: Mapping 1 to 1 relationship and persisting in kotlin

Hello together I am currently trying to persist an entity to the database with a 1 to 1 relationship.
I am using spring version 2.5.3 (spring-boot-data-jdbc).
When I try to persist via rest post and the usual crud repository save() method with this json.
{
"name": "everyday at 15",
"announcement": {
"name": "This is the third announcement"
}
}
I get this error message:
2021-08-19 14:20:06.315 ERROR 7946 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.relational.core.conversion.DbActionExecutionException: Failed to execute DbAction.InsertRoot(entity=Timetable(id=null, name=everyday at 15, announcement=Announcement(id=null, name=This is the third announcement)))] with root cause
org.postgresql.util.PSQLException: ERROR: insert or update on table "timetable" violates foreign key constraint "fk_announcement"
Detail: Key (announcement)=(6) is not present in table "announcement".
It seems like the counter for the announcement id is always going up however it never reaches the point where anything is persisted.
My entity and db setup are listed below.
#Table("announcement")
data class Announcement(
#Id
val announcement_id: Long?,
val name: String
)
#Table("timetable")
data class Timetable(
#Id
var id: Long?,
val name: String,
val announcement: Announcement
)
CREATE TABLE announcement(
announcement_id serial,
name varchar(30) not null,
PRIMARY KEY(id)
);
CREATE TABLE timetable(
id serial,
name varchar(30) not null,
announcement_id serial,
PRIMARY KEY(id),
CONSTRAINT fk_announcement
FOREIGN KEY (announcement_id)
REFERENCES announcement (announcement_id)
);
Thank you for your help!
Since Timetable is your aggregate root, the foreign key should be placed on the announcement table, not on the timetable table.
Note that Announcement.announcement_id is superfluous as far as Spring Data JDBC is concerned. In the following schema I left it in but put the primary key on the new timetable column:
CREATE TABLE announcement(
announcement_id serial,
timetable biginteger, -- the correct type to use depends on the database you use.
name varchar(30) not null,
PRIMARY KEY(timetable),
CONSTRAINT fk_announcement_timetable
FOREIGN KEY (timetable)
REFERENCES timetable (announcement_id)
);
CREATE TABLE timetable(
id serial,
name varchar(30) not null,
PRIMARY KEY(id)
);

Room Persistence Library - CREATE VIEW

I need to use a SQL VIEW in a query using Room Persistence Library.
Using Commonsware's answer here I've been able to run a raw SQL statement to create the view during DB creation.
Room.databaseBuilder(context, MyDatabase.class, DB_NAME)
.addCallback(new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
db.execSQL("CREATE VIEW view_name " +
"AS SELECT [...] "
);
}
})
.build();
The VIEW is actually created on the SQLite DB and works fine, but I cannot refer to the it in my Dao's #Query because I get a compile-time error:
Error:(100, 48) error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such table: view_name)
Any idea on how to let Room to know about my view or to ignore the error?
UPDATE 17/12/2018
Version 2.1.0 and higher of the Room persistence library now provides support for SQLite database views:
https://developer.android.com/training/data-storage/room/creating-views
(see D-D's comment)
UPDATE 15/12/2017
Be aware that this solution actually breaks DB migrations.
Problem is with the Entity primary key that obviously doesn't exist on the view, so migration is not valid.
See CommonsWare's comment for a possible hacky workaround.
ORIGINAL ANSWER
It seems that this is not possible at the moment using Room.
Anyway I've done it using a workaround: I've created an Entity with the same name and columns as the view (only the name is actually mandatory), this will create a table on DB and allow you to use that table name in queries without compile-time errors.
Then during Room DB creation I DROP this entity's table just before the CREATE VIEW.
Room
.databaseBuilder(context, DueDatabase.class, DB_NAME)
.addCallback(new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
//Drop the fake table and create a view with the same name
db.execSQL("DROP TABLE view_name");
db.execSQL("CREATE VIEW view_name " +
"AS SELECT [...]"
);
}
})
.build();

How to catch grails.validation.ValidationException?

I have simple domain:
package app
class Customers {
String CUSTOMER
String NOTE
static mapping = {
version false
id column: 'ID_CUSTOMER', type: 'long',
generator: 'sequence',
params: [sequence: 'CUSTOMER_SEQ']
}
static constraints = {
CUSTOMER(nullable: false, blank: false, unique: ['NOTE'])
NOTE(nullable: true, blank: true)
}
}
Columns and constraints are created properly in database (I want constraint on customer and note together), but instead of getting:
grails.validation.**ValidationException**
I am getting:
Message: Hibernate operation: could not execute statement; SQL [n/a]; ORA-00001: unique constraint (TEST2.UNIQUE_CUSTOMER_NOTE) violated
; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (TEST2.UNIQUE_CUSTOMER_NOTE) violated
Shouldn't I get ValidationException when constrains are violated?
Controller code is standard auto code generated by the generate-all script.
You don't show any of the controller code - are you checking the return value of validate() and save() calls (or using hasErrors()) and redirecting back so the user can fix the mistakes?
What you're seeing will happen if you change one or both values and they're no longer unique, but you don't call validate() or save(). That's because at the end of the request, any modified instances will be updated in the database because the session gets flushed, and Hibernate uses its cached copy of the original values to detect modified/dirty instances that haven't been saved and flushed yet.
If you change a value but don't plan on saving the change (e.g. if you set values only for rendering the GSP) be sure to evict the instance from the session by calling discard() - Hibernate won't try to push those changes if the instance is no longer attached to the session.

Grails - Using a VARCHAR2 field as table identifier - foreign key relationship fails

I am integrated with a legacy Oracle database which uses assigned VARCHAR2 values for primary keys. I am creating a one-to-many relationship with this existing table. The legacy table is called Applications (which I may not alter) and the new table is called Projects. Many projects may be assigned to one application.
When GORM creates the Project table it is creating a NUMBER column for the foreign key, application_id, even though this is a VARCHAR2 field in the Applications table.
class Application {
static hasMany = [projects : Project]; // does not fix problem
String application_id;
...
static mapping = {
table 'applications'
version false
id (column:'application_id')
}
static constraints = {
application_id(maxSize:16,blank:false,unique:true,type:"string",generator:"assigned")
}
...
}
class Project {
Application application;
...
}
When I compile the app I get warnings like this:
Unsuccessful: alter table project add constraint FKED904B1956694CB5 foreign key (application_id)
ORA-02267: column type incompatible with referenced column type
When I run the app and click on Application controller I get this error:
SQL state [99999]; error code [17059]; Fail to convert to internal representation; nested exception is java.sql.SQLException: Fail to convert to internal representation
When I click on Project | create I get this error:
Fail to convert to internal representation; nested exception is java.sql.SQLException: Fail to convert to internal representation at /project/create:172
So how can I set the Project class to expect a VARCHAR2 foreign key for the Application?
Thanks for any help!
Look at this site. Maybe it will help you.
Here is the correction in the Application class... in case anyone else searches for this:
class Application {
static hasMany = [projects : Project];
String application_id;
String id // <--- part of solution
static mapping = {
id column:'application_id',generator:'assigned' // <--- part of solution
}
static constraints = {
application_id(maxSize:16,blank:false,unique:true) // <--- part of solution
columns { // <--- part of solution
id type:'text'
application_id type:'text'
}
}

Resources