Get back UniqueID after persist JPA - java

I have a uniqueID of date + sequence in Oracle. Example: 20130307-000021
My entity object uniqueID looks like this:
#Id
// #GeneratedValue
// #Basic(optional = false)
// #NotNull
// #Size(min = 1, max = 15)
#Column(name = "UNIQUE_ID")
private String uniqueId;
Anytime I use #GeneratedValue or it's variants I get a "sequence not found" or some other error. I'm trying to get back the unique ID that is generated by the Oracle database after I persist an object.
this.dbConn.persist(orderDetail);
this.dbConn.flush();
//this.dbConn.refresh(orderDetail);
//OrderDetails od = new OrderDetails();
//od =(OrderDetails)this.dbConn.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(orderDetail);
The above are some various things I've tried. When I use refresh I get an error saying "entity" not found (I assume it is looking up the entity based on the pre-persisted uniqueID of null. Is it possible to get back that auto-generated date+sequence number? I'm able to persist and retrieve objects just fine by looking at the inserted object and copying the uniqueID directly but obviously that is useless. Any help much appreciated and if you would like to see error messages etc just let me know. I've searched around and I either see 'solutions' that appear to be what I am trying or one person said he used a "brute-force work-around" but did not describe what that meant.

For anyone that may happen upon this. I kept the database trigger and just used:
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 15)
#Column(name = "ORDER_ID")
private String orderId;
I didn't need to use #GeneratedValue or any of its variants.

Related

Store multiple Strings in a single postgresql record using Spring jpa

I found this question with different programming languages or different database
Im trying to make a portal to generate multiple choice quizes
the front end will send me a huge json at some point there will be an array of Questions objects
evry object should have:
the question
the right answer
a list of wrong answers ( min 2 max 4 )
the id of the CourseSpecifics object...
I need to store (if possible) the list of wrong answers ( Strings ) in a single record of my postgresql db
this is my class
#Entity
#Table(name = "questions")
public class Questions {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name ="question",nullable = false)
String question;
#Column(name ="answer",nullable = false)
String answer;
#Column(name ="wrong_answers",nullable = false)
List<String> wrongAnswers;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="fk_specifics",nullable = false)
CourseSpecifics fkSpecifics;
}
This is the exact point where i have some doubts (lets skip the rest for the moment, i know i can improve it )
#Column(name ="wrong_answers",nullable = false)
List<String> wrongAnswers;
im also using spring.jpa.hibernate.ddl-auto=create to generate db from spring structure but its not mandatory
My questions are :
What is the best data type to use on spring in this situation for wrongAnswers ?
What is the best column definition to use on db according to the data type of wrongAnswers ?
You're likely looking for the #ElementCollection annotation. This will allow you to have a list of strings as you have it right now.
However, it use a new table! Which you don't seem to want. Without binding yourself to a single database (by using arrays or something) your best bet may be to write a converter to serialize a list of strings into a single string.
I'd personally revaluate if your single record is a super strong requirement.

Java JPA Hibernate OneToOne vs HashMap - Which One Should I Use and Why?

I have a question about performance and common practice, if someone could explain this to me.
I have recently started using JPA and hibernate and have come across an Entity that has a foreign key and I need to get some data from it. So for example: CustomerAddress has a City and that city has a lot of detail and also a name.
SQL:
select
CA.Id, CI.Name
from
CustomerAddress as CA
inner join City as CI
on CA.CityID = CI.Id
So now in Java JPA Entity I can have a one-to-many annotation:
#Entity
#Table(name = "CustomerAddress")
public class CustomerAddressEntity {
#Id
#Column(name = "Id", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#NotFound(action = NotFoundAction.IGNORE)
#JoinColumn(name = "city", referencedColumnName = "id", insertable = false, updatable = false)
private City city;
}
Where City is also an #Entity with #Id and simple object.
Which in my opinion does not turn out the best because it makes a lot of SQL requests.
And then I have the option having just two findAll() calls at the beginning, where I would collect all the City Entities in a HashMap<String, City> and when needing the name I would just call hashmap.get(key).getName().
EDIT (thanks for the heads up :)):
And when using this HashMap I can use a simpler Entity without the #JoinColumn
#Entity
#Table(name = "CustomerAddress")
public class CustomerAddressEntity {
#Id
#Column(name = "Id", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "CityID")
private Long cityId;
}
In the hashmap case I only get two SQL calls and I think it works much faster. Is there a way to get this behavior also using JPA and hibernate?
If my question and code needs some more refinement please let me know.. I can edit the question with more details and perhaps if necessary provide a working example. Thank you for your thoughts :)
And the same would go for OneToMany, where the hashmap would be: new HashMap<String, List<City>> for example - I mean the whole example should be created a bit differently - I guess it could even be a HashMap<String, HashMap<String,City>> - if one would need quick access to the City by Id or sth... but i digress :) I will edit the question and respond to comments as I will go.. and refine the question if necessary.. I would just like to hear some thoughts and where my thinking is wrong :) and what am I failing to see and missing :)
EDIT: For example a code that would create a lot of SQL requests:
public interface CustomerAddressRepository extends JpaRepository<CustomerAddressEntity, Long> {
#Override
List<CustomerAddressEntity> findAll();
}
This for example creates an SQL Query (I would use findAll() at the beginning to list all - or most of the Entities for the user) and you would get an SQL query for every Entity because it would want to find the Name of the City as well - because the ID of the City Entity does not really help to the user.
Also - I like to have all the Entities in my RAM so I can do a quick search for the user more responsive - So a search does not always do SQL Query + #(found results) Queries.
The HashMap has nothing to do with the fact that Hibernate issues a query when you want to get the name of the City object.Here's why it's happening.
In your CustomerAddressEntity you have a OneToOne with City , and since you have a #JoinColumn there ,it means that CustomerAddressEntity database Table will have the Primary Key of the City table as a foreign key , and since you specified in your class that it should be fetched LAZY,Hibernate will create a Proxy object wrapping the City object,ready to get queried from the database in case you call any getMethod ,like getName() ,(excluding the getId() method since the ID exists prealably in the proxy object,you can check the sql query logs and see that the query selects the foreign key with all the other fields of CustomerAddressEntity ),that's why when you trigger the getName() method Hibernate will fetch that entity from the database.

Hibernate Envers - select "all" changes for entity ID

I have problem with Hibernate Envers.
I have classes like:
#Entity
#Table(name = "REVINFO")
#RevisionEntity(MyRevisionEntityListener.class)
public class RevEntity {
#Id
#RevisionNumber
#Column(name = "REV", nullable = false, updatable = false)
private Integer id;
#RevisionTimestamp
#Column(name = "REVTSTMP", nullable = false, updatable = false)
private Date timestamp;
#Column(name = "MODIFIED_BY", length = 100)
private String modifiedBy;
#Column(name = "COMMENT", length = 100)
private String comment;
public class MyRevisionEntityListener implements RevisionListener {
#Override
public void newRevision(Object revisionEntity) {
RevEntity a = (RevEntity) revisionEntity;
a.setComment("Some value");
}
}
How can i select every change for entity ID and their "REVINFO" object?
I've got something like this:
List resultList = AuditReaderFactory.get(entityManager)
.createQuery()
.forRevisionsOfEntityWithChanges(ClientType.class, true)
.add(AuditEntity.id().eq(entityId))
.getResultList();
And it's almost work good. I received every "change" but REVINFO looks strange. All fields are null - and there are 1 more object $$_hibernate_interceptor which actually hold "information" but i cannot acces it via code (or i dont know how). See example at the image.
So my question is:
1 - How can i get REVINFO values ?
2 - Do i realy have to use entityManager, or can it be achived with different approach ?
Edit 2:
Correct me if i am wrong, but does forRevisionsOfEntityWithChanges works as Lazy Initialization? I mean, if i try to receive for example modifiedBy field i actually get my data. Debugger log make me confused.
The call to forRevisionsOfEntityWithChanges returns an object array that contains:
Entity instance
Revision Entity
Revision Type
Property names that were changed.
How can i get REVINFO values ? 2 - Do i realy have to use entityManager, or can it be achived with different approach ?
So in your code, to get the revision info attributes, you would do the following. Note that in this code, the type of the revision-info object will depend on your configuration or if you're using a custom revision-info entity class in your deployment. Just be sure to cast it to the proper type.
for (Object entry : resultList) {
final Object[] row = (Object[]) entry;
final TheRevisionEntityClassType revisionInfo = row[1];
// now you can get the revision entity attributes from revisionInfo using getters
}
Correct me if i am wrong, but does forRevisionsOfEntityWithChanges works as Lazy Initialization? I mean, if i try to receive for example modifiedBy field i actually get my data. Debugger log make me confused.
Depending on the query, yes Hibernate may use proxies and its important to understand that in this case, the visual representation you get in the debugger may or may not be accurate depending if the object's internal state gets initialized by the debugger window or not.

JPA foreign key zero 0 value hibernate TransientPropertyValueException

I have found that hibernate (or mariadb) JPA does not seem to work with 0 values in a foreign key.
I have a parent class
class Parent {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PARENT_ID", unique = true, nullable = false)
private Integer parentId;
}
And a child class
class Child {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "CHILD_ID", unique = true, nullable = false)
private Integer childId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "PARENT_ID", nullable = false)
private Parent parent;
}
So we have 2 rows in parent. parent_id=0 and parent_id=1
My problem is that I get an error when attempting to use parent with ID 0. i.e. This code
Parent p = entityManager.find(Parent.class, new Integer(0));
Child c = new Child();
c.setParent(p);
entityManager.persist(c);
Will fail with the error:
java.lang.IllegalStateException:
org.hibernate.TransientPropertyValueException: Not-null property
references a transient value - transient instance must be saved before
current operation : com.whatever.Child.parent -> com.whatever.Parent
But the following works fine:
Parent p = entityManager.find(Parent.class, new Integer(1));
Child c = new Child();
c.setParent(p);
entityManager.persist(c);
So I assume the PARENT_ID=0 somehow confusing JPA into thinking it is not a valid parent object.
Or is this actually a mariadb issue? Related to the fact that you have to change a session setting in order to insert 0's into AUTO_INCREMENT columns.
Is there any config or annotation I can do to make this work. Unfortunately we are putting JPA code on an existing system, so changing the PARENT_ID values is not a trivial task. (and everybody hates data conversion).
Any tips very much appreciated.
MariaDB/MySQL handle AUTO_INCREMENT thus: Numbers are 1 or greater; 0 is a valid sequence number. If JPA cannot live with those (and some other) limitations, JPA is broken. (Sorry, but I get irritated with 3rd party software that makes life difficult for MySQL users.)

How to create foreign key in Hibernate on Integer column

I have an entity in Java and I would like Hibernate to create a foreign key from an Integer field (since I don't have an object reference):
#Entity
public class Invoice {
...
#Column(nullable = true)
private Integer generatedBy;
...
I think I'd like to do something like this with an attribute:
#ForeignKey(name="FK_Invoice_GeneratedBy", references="UserTable.UserId")
#Column(nullable = true)
private Integer generatedBy;
What is the best way to achieve this? I would preferably not have to maintain these relationships in a separate file (if possible).
There doesn't seem to be a solution to this, thus accepting this as an answer.
There is a way to do it, but it is not very nice...
You can have your integer attribute, AND an object attribute mapped this way:
#Column(ame = "GENERATED_BY", nullable = true)
private Integer generatedBy;
#ForeignKey(name="FK_Invoice_GeneratedBy")
#JoinColumn(name = "GENERATED_BY", nullable = false, updatable = false, insertable = false)
private User generatedByUser;
You may keep no external access to your generatedByUser field, it will only show hibernate that there is a relationship. You can set the Integer field at will, when you load this object from DB later you'll have your user reference.
Again, not very pretty, but can be useful sometimes.

Categories