EclipseLink can not insert an entity into oracle - caching

I built an entity with id using oracle sequence like that.
#Entity
#Table(name="C_ESTIMATE")
public class Estimate implements Serializable{
private static final long serialVersionUID = 1L;
public Estimate(){}
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "estimatenoGen")
#SequenceGenerator(name="estimatenoGen",sequenceName="AUTOSERIALNO",allocationSize=1)
#Column(name="ESTIMATENO")
private long id;
}
When I call em.persist(new Estimate()),
EclipseLink prompts Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraints . Sometimes it works correctly, sometimes failure, it is so strange.
This entity was deployed several weblogic servers.
Has EclipseLink bug on generating id using oracle sequence?

There should not be any issue on Oracle.
Can recreate the issue? Enable logging, is a duplicate id being used?
How did you create your SEQUENCE object on the database?

Related

Spring data jpa does not update existing row (Oracle) when using #sequencegenerator

New to spring data JPA. I have sequence created in oracle table. I am using JPARepository saveall() method to save the data. Inserts work without any problem but when i try to update any existing rows in the table it always tries to insert throwing unique constraint error since i have unique index created for that table.
Entity Class
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator1")
#SequenceGenerator(sequenceName = "emp_seq", name = "generator1",allocationSize = 1)
#Column(name = "USER_ID")
private Long id;
Save method invocation
public void persistEmployees(List<Employee> employees) {
employeeRepo.savaAll(employees);
}
Repository class
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> { }
How can i tell JPA to look for existing row before inserting? Any help is much appreciated!!!
In My Humble Opinion;
Using "Exists" condition-check as "sub-query" for all constrained columns, before Update will solve this.

Has Spring-boot changed the way auto-increment of ids works through #GeneratedValue?

Spring-Boot 2.0.0 seems to have modified the way Hibernate is auto configured.
Let's suppose two simple and independent JPA entities:
#Entity
class Car {
#Id
#GeneratedValue
private long id;
//....
}
#Entity
class Airplane {
#Id
#GeneratedValue
private long id;
//....
}
Prior, using Spring-Boot 1.5.10, I was able to generate separate sequences of auto-increments, meaning that I can get a Car with 1 as primary key and an Airplane with 1 as primary key too.
No correlation between them, e.g no shared sequence.
Now, with 2.0.0, when I sequentially create a very first Car then a very first Airplane, the car gets 1 as id and airplane gets 2.
It seems that he has to deal with the GeneratedType.AUTO, that is the "used by default" specified within the #GeneratedValue annotation source.
However, my reasoning seems to stop here since GeneratedType.AUTO was also set as default with the 1.5.10.
A simple workaround to fulfil my expectation is to specify the IDENTITY strategy type of generation like so:
#Entity
class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//....
}
#Entity
class Airplane {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//....
}
I can't figure out an explanation of this behavior.
What has Spring-boot 2.0.0 changed, explaining this scenario?
Spring Boot 2.0 uses Hibernate 5.2 (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes).
Hibernate changes its GeneratedType.AUTO strategy since 5.2. Any database that does not support sequences natively (e.g. MySQL), they use the TABLE generator instead of IDENTITY. (https://hibernate.atlassian.net/browse/HHH-11014)
That's why GeneratedType.AUTO does not work as you expected.
You can use
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
to use MySQL autoincrement.
If you are in need for a quick, not future-proof solution to prevent this issue from happening:
spring.jpa.hibernate.use-new-id-generator-mappings=false, as from the Spring Boot 2 docs:
spring.jpa.hibernate.use-new-id-generator-mappings= # Whether to use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.
This will prevent from using the new generators and keep the old functionality included in Spring boot 1.x.x.
Please note that this is probably not the best solution, but it is very helpful on short term
As Andrew has pointed out in the comment, if you don't want the id to be incremented while values are created in other tables, you can specify your ID like this:
#Id
#GeneratedValue(
strategy= GenerationType.AUTO,
generator="native"
)
#GenericGenerator(
name = "native",
strategy = "native"
)
private Long id;
Doing this will make each table has its unique id beginning with 1,2,3 ... and so on.
By default spring-boot uses the auto and increment the value based on the order the objects are saved.
To provide unique id based on each object, use the following
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

Relational database foreign keys in Spring Boot JPA/Hibernate

I'm using Spring Boot JPA with Gradle. I'm struggling to find a guide that I can follow which focusses on creating a relational database with the correct Syntax for Spring Boot. I had a go but I get this error
No property idTestCase found for type TestRun!
I want TestRun and TestData entities with a OneToOne relationship with each other, and a TestCase entity that has a OneToMany relationship with TestRun. I reckon that TestRun should contain the foreign keys for TestData and TestCase.
Many times I make changes and it will not build, and when it does build the tables do not look correct, this is what I created:
#Entity
public class TestRun {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private long testRunId;
private Boolean result;
#OneToOne #JoinColumn(name="testData_id")
private TestData testData;
#ManyToOne #JoinColumn(name="testCase_id")
private TestCase testCase;
}
#Entity
public class TestCase {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private long testCaseId;
private String name;
private String description;
#OneToMany(cascade=CascadeType.ALL, mappedBy="testCase",targetEntity=TestRun.class)
private Collection<TestRun> testRun;
}
#Entity
public class TestData {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private long testDataId;
#OneToOne(cascade=CascadeType.ALL, mappedBy="testData",targetEntity=TestRun.class)
private TestRun testRun;
}
From the guides it isn't clear to me what goes in #JoinColumn(name= some say it needs to link to a field on your POJO and some say it doesn't. If I create the foreign key field in my POJO then I get two foreign key fields in the database table and if I don't it doesn't build at all.
For example from the error I can infer it wants me to add the following fields to TestRun:
private long idTestCase;
private long idTestData;
But then my database appears as:
SELECT * FROM TEST_RUN;
TEST_RUN_ID
ID_TEST_CASE
ID_TEST_DATA
RESULT
TEST_CASE_ID
TEST_DATA_ID
(no rows, 3 ms)
I tried setting #JoinColumn(name= to the name of the primary key field on the other side of the relationship but again it did not build.
Many thanks
I found the guide at JBoss to be the most helpful in describing the different mappings.

No foreign key exist in db created

I have created many entities in jpa.
When i checked in the database, i don't see any foreign key.
#Entity
public class Lodger implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long lodgerId;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<AccountOperation> accountOperationList;
...
}
#Entity
public class AccountOperation {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long accountOperationId;
#ManyToOne
#JoinColumn(name = "lodger_id")
private Lodger lodger;
...
}
In this example i was thinking to get a foreign key in the account operation class.
table automaticaly created
http://www.wepaste.com/table_example/
Why?
Hibernate does not automatically generate foregein keys when generating dlls. I would recommend to turn of the generate-dll option as it may create inconsistent databases as the complexity increases. also check out either spring boot default database administration options:
Flyway
Liquibase
The main difference between the two relies in the fact that while both may be administrared with SQL, Liquibase offers a more database agnostic formats such as XML, and YML for the creation of your database

EclipseLink 2.1.3, Oracle 11g, return PK after persist with container managed persistence

I'm using EclipseLink 2.1.3 with a container managed EntityManager to interface with an Oracle 11g DB.
I want to have an Entity's #Id variable updated immediately after I call persist() on the EM.
What is the correct strategy to do so with an Oracle DB?
None of the examples I've found on this site deal with this problem with container managed persistence.
The Entity looks like this:
#Entity
#Table(name = "ANNOUNCEMENT_DELIVERY_LOG")
public class AnnouncementDeliveryLog implements Serializable {
#Id
private BigDecimal id;
#ManyToOne
#JoinColumn(name = "ANNOUNCEMENT_ID ")
private Announcements announcement;
public AnnouncementDeliveryLog() {
}
}
Do I need to add something like the following?
#Column(nullable = false)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
#SequenceGenerator(name="ANNOUNCEMENT_DELIVERY_LOG_SEQ", sequenceName="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
To persist the Entity I'm just calling persist(). Do I also need to call flush()?
Yes, you have to provide a #SequenceGenerator annotation in order that JPA automatically assigns a new ID to the entity during persist().
A flush is not necessary.

Resources