JPA: Usage of #GeneratedValue on non-id column - jpa

I am attempting to persist an entity with an attribute that I want to be populated from a DB sequence. I'm using Oracle, have created the sequence, verified the sequence works via sql, and yet my attribute isn't getting populated. Here's what I have:
#GeneratedValue(generator = "RFQ_LINE_IDS_SEQUENCE", strategy=GenerationType.SEQUENCE)
#SequenceGenerator(name="RFQ_LINE_IDS_SEQUENCE", sequenceName="RFQ_LINE_IDS_SEQUENCE", allocationSize=1000000000)
#Column(name = "external_line_item_id")
private String externalLineItemId;
All the examples I'm seen online show this annotation being used with #Id, but I have another attribute that I'm using for my id.
I've also tried the following to no avail:
#GeneratedValue(generator = "RFQ_LINE_IDS_SEQUENCE", strategy=GenerationType.SEQUENCE)
#GenericGenerator(name = "RFQ_LINE_IDS_SEQUENCE", strategy = "sequence",
parameters = {#Parameter(name = "sequence", value = "RFQ_LINE_IDS_SEQUENCE")})
#Column(name = "external_line_item_id")
private String externalLineItemId;

JPA only mandates support for #GeneratedValue on #Id fields. Some JPA implementations (such as DataNucleus JPA) support it but not all do.

I have created a proposal for JPA to support #GeneratedValue for non-id attributes. Please vote here for this to be included in 2.2
https://java.net/jira/browse/JPA_SPEC-113

Related

How to define custom sequence generator used for Id (primary) in JPA?

My application is using JPA for persisting data to Database.
The application has to generate Custom(encoded) sequence for performance reasons.
By default JPA seems to generate Ids for an entity using some sequence.
How to override default sequence generator with customer sequence generator in Java ? I want to have sequence generator in Java as I have a separate logic for that.
This is how you go with the custom sequence:
#Id
#SequenceGenerator(name = "pet_seq",
sequenceName = "pet_sequence",
initialValue = 1, allocationSize = 20)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pet_seq")
#Column(name = "id", nullable = false)
private Long id;
In this case it will use pet_sequence instead of the default one. Also you can read this article for a better understanding of this subject.

Alternative initial value for entity in JPA

I have the following entity and their mapping
#Entity
#Table(name = "test")
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator", initialValue = 20000)
I want id value begins in 20000 but it doesn't work in postgresql. When the application starts I receive this exception
Caused by: org.hibernate.HibernateException: Multiple references to
database sequence [sequence_generator] were encountered attempting to
set conflicting values for 'initial value'. Fou nd [20000] and [1]
Do I need a extra configuration to it works?
PS: It is a new database without any previous configuration
You could try #TableGenerator annotation. Initial values can be set and seed other values.
You can find example and documentation here:
Set Initial Value Of Table Generator

Spring JPA Entities: related problems of Ignite error, LAZY fetching, and too-m, minimizing database use and working with Ignite

I'm writing some entity relationships using Spring Data and Java. I have this pair of classes (edited):
Subject:
#Entity
#Table(name = "SUBJECT")
// Lombok, etc., attributes removed
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID", updatable = false, nullable = false)
#JsonProperty("id")
private Long id;
#OneToMany(targetEntity = SubjectResource.class, mappedBy = "subject", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<SubjectResource> resources;
}
SubjectResource:
#Entity
#Table(name = "SUBJECT_RESOURCE")
// Lombok, etc., attributes removed
public class SubjectResource {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID", updatable = false, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "SUBJECT_ID")
private Subject subject;
}
I'm trying to solve these issues:
Question 1: Can I manipulate #OneToMany or #ManyToOne to NOT have the child class recurse its parent?
Fetch of resources returns subject data:
/subject/101:
{"id":101,"resources":[{"id":1001,"subject":101},{"id":1002,"subject":101},{"id":1003,"subject":101},{"id":1004,"subject":101}]}
/subjectResource/1001:
{id:1001,subject:{"id":101,"resources":[{"id":1001,"subject":101},{"id":1002,"subject":101},{"id":1003,"subject":101},{"id":1004,"subject":101}]}}
That is, /subjectResource/1001 returns its ID and the entire /subject/101 query.
How can I have just the subjectResource data, without its parent?
Question 2: Through #OneToMany or #ManyToOne can I get Hibernate to fetch on a "1" (O(1)) basis?
When /subjects does its thing, it works with Hibernate on a "n+1" (O(n)) basis: 1 fetch of subjects, n fetches of resources, one for each subject ID.
I could force a single fetch through a fancy repository #Query annotation ("select s from subject s left join fetch s.resources"). But that means putting the subject : subject_resource definitions in two places, etc.
Can JPA implementation / Hibernate be forced to do a join, and thus make only one database call, through annotation within an entity class?
Question 3: How do I get my Spring Data / Spring Repository to cooperate with Ignite, and have the cache return the data it already had on the first call?
I'm usng FetchType.LAZY, as all good pupils do. I'm also storing things in Apache Ignite. For /subject/101 the initial call fetches everything OK, returning it in JSON. But the second call gets from the Ignite cache, which complains about being out of transaction.
How do get my LAZY fetches to cooperate with Ignite?
Thanks,
Jerome.

Why does IntelliJ's JPA inspection tell me "more than one attribute configured for field 'id'"?

I have many JPA entity classes of the general form:
#Entity
#Table(name = "MY_TABLE", catalog = "", schema = "VBMSUI")
#NamedQueries({...})
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "ID")
#GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="MY_TABLE_ID_SEQ")
#SequenceGenerator(name="MY_TABLE_ID_SEQ",
sequenceName = "MY_TABLE_ID_SEQ")
private BigDecimal id;
...
}
IntelliJ's inspection facility underlines "id" in red, and provides the message - "more than one attribute configured for field 'id'".
There are no other attributes in the class identifed as an id. There is a getter and a setter for "id", but they have no annotations. BTW, the code for the entity class was generated by NetBeans, and it seems to work.
What is happening, and how can I correct it?
This seems to happen because you have both #Id and #Basic annotations on the same attribute (quick fixes suggest removing either one of them). I'm no expert in JPA, but it looks valid to me, so perhaps it is a bug in IntelliJ's inspection, which should be reported in their bugtracker.
It appears that this is a bug. It has been reported as such here: https://youtrack.jetbrains.com/issue/IDEA-129147 You can up-vote it if you wish to see a resolution.

Adding entity doesn't refresh parent's collection

the question and problem is pretty simple, though annoying and I am looking for a global solution, because it's application-wide problem for us.
The code below is really not interesting but I post it for clarification!
We use PostgreSQL database with JPA 2.0 and we generated all the facades and entities, of course we did some editing but not much really.
The problem is that every entity contains a Collection of its children, which however (for us only?) is NOT updated after creation a children element.
The objects are written to database, you can select them easily, but what we really would like to see is the refreshed collection of children in parent object.
Why is this happening? If we (manually) refresh the entity of parent em.refresh(parent) it does the trick but it would mean for us a lot of work in Facades I guess. But maybe there is no other way?
Thanks for support!
/* EDIT */
I guess it has to be some annotation problem or cache or something, but I've already tried
#OneToMany(mappedBy = "idquestion", orphanRemoval=true, fetch= FetchType.EAGER)
and
#Cacheable(false)
didn't work properly.
/* EDIT */
Some sample code for understanding.
Database level:
CREATE TABLE Question (
idQuestion SERIAL,
questionContent VARCHAR,
CONSTRAINT Question_idQuestion_PK PRIMARY KEY (idQuestion)
);
CREATE TABLE Answer (
idAnswer SERIAL,
answerContent VARCHAR,
idQuestion INTEGER,
CONSTRAINT Answer_idAnswer_PK PRIMARY KEY (idAnswer),
CONSTRAINT Answer_idQuestion_FK FOREIGN KEY (idQuestion) REFERENCES Question(idQuestion)
);
Than we have generated some Entities in Netbeans 7.1, all of them look similar to:
#Entity
#Table(name = "question", catalog = "jobfairdb", schema = "public")
#XmlRootElement
#NamedQueries({ BLAH BLAH BLAH...})
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "idquestion", nullable = false)
private Integer idquestion;
#Size(max = 2147483647)
#Column(name = "questioncontent", length = 2147483647)
private String questioncontent;
#OneToMany(mappedBy = "idquestion", orphanRemoval=true)
private Collection<Answer> answerCollection;
Getters... setters...
We use (again) generated facades for them, all implementing AbstractFacade like:
public abstract class CCAbstractFacade<T> {
private Class<T> entityClass;
public CCAbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
The father entity is updated automatically if you use container managed transactions and you fetch the collection after the transaction is complete. Otherwise, you have to update yourself the collection.
This article explains in detail this behaviour: JPA implementation patterns: Bidirectional associations
EDIT:
The simplest way to use Container Managed Transactions is to have transaction-type="JTA" in persistence.xml and use Container-Managed Entity Managers.
You seem to be setting the ManyToOne side, but not adding to the OneToMany, you have to do both.
In JPA, and in Java in general you must update both sides of a bi-directional relationship, otherwise the state of your objects will not be in sync. Not doing so, would be wrong in any Java code, not just JPA.
There is no magic in JPA that will do this for you. EclipseLink does have a magic option for this that you could set through a customizer (mapping.setRelationshipPartnerAttributeName()), but it is not recommended, fixing your code to be correct is the best solution.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side