What will actually happen if I provide a full set of annotations for JPA and JDO on data objects?
Can I then switch between them without touching the code? how can I switch what to aplay external configuration files? I know in the META-INF there are persistence.xml jdoconfig.xml but I do not understand the how to use them. (may be a link to a compressive explanation?)
Currently I got both files in place and the code below compiles Ok. I am interested in what goes under the hood to understand implications of this approach.
For vivid example:
#Entity
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
class B
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Persistent
#Basic
private String name;
}
Platform: default setup of Google AppEngine 1.4 it uses DataNucleus Enhancer (version 1.1.4)
Although I have never try this it should work. This is the point of annotations: the do not affect the code unless they are used. JPA implementation uses its annotations, JDO uses others.
Related
I built an application with Quarkus and I'm using Hibernate with Panache for the models. Everything goes well, the application starts, but when I call a webservice to get a list using Panache functionalities (.listAll()), I get an empty list and I see the following message in the console:
HHH000183: no persistent classes found for query class: from com.myproject.model.TeamEntity
My models are defined with #Entity annotations that should allow Hibernate to find by itself the entity mappings. Here is an example with the Team model:
#Entity
#Table(name = "TEAM")
public class TeamEntity extends PanacheEntityBase {
#Id
#GeneratedValue(strategy = SEQUENCE, generator = "TEAM_SEQ_GEN")
#SequenceGenerator(name = "TEAM_SEQ_GEN", sequenceName = "TEAM_SEQ", allocationSize = 10)
#Column(name = "ID_TEAM", nullable = false)
private int id;
#Column(name = "NAME", nullable = false)
private String name;
...
}
I don't have any persistence.xml file in the project, only the application.properties linked with Quarkus. Here are the relevant properties extracted from mine:
quarkus.datasource.db-kind=oracle
quarkus.datasource.jdbc.url=jdbc:oracle:thin:/#MYWALLET
%dev.quarkus.datasource.jdbc.url=jdbc:oracle:thin:MYUSER/MYPASSWORD#localhost:1521/SAA
quarkus.datasource.jdbc.driver=oracle.jdbc.OracleDriver
quarkus.datasource.jdbc.min-size=2
quarkus.datasource.jdbc.max-size=10
quarkus.datasource.jdbc.new-connection-sql=alter session set current_schema=MYSCHEMA
quarkus.hibernate-orm.dialect=org.hibernate.dialect.Oracle12cDialect
Does someone know where the problem could come from ? Hibernate should detect entities with annotations and use them in queries automatically.
It came out that the problem was on Quarkus Datasource configuration in the application.properties file. More particularly from this specific line to define the schema used at first connection (I have to admit that was not good looking):
quarkus.datasource.jdbc.new-connection-sql=alter session set current_schema=MYSCHEMA
Replacing the line above with the following solved the problem:
quarkus.hibernate-orm.database.default-schema=MYSCHEMA
In conclusion, I think Hibernate cannot find / does not take the entities defined if this property is not defined, maybe because it makes some kind of detection beforehand. That's only a supposition, if someone knows more precisely how Hibernate works for that specific case, I would be very interested !
Versions:
Hibernate-Core: 5.2.5.Final
Hibernate-Search: 5.5.5.Final
Having the following mappings:
#Indexed
#Entity
#Table(name = "scanresult")
public class ScanResult
{
#Id
private ScanResultKey id;
#Field
#Column(name = "name")
private String name;
}
#Embeddable
public class ScanResultKey implements Serializable
{
#ManyToOne
#JoinColumn(name = "eA", referencedColumnName = "id")
private EntityA entA;
//others...
}
I have read in previous posts that this was an issue in Search 4.4 (when having composite id and foreign relations), but this should be fixed in 5.5. So apparently it is my fault. But I can't figure out what could I do wrong
Exception:
org.hibernate.search.exception.SearchException: HSEARCH000135: Unable to guess FieldBridge for id in entities.keys.ScanResultKey
Note: I only need one field(name) to be indexed
Could you please point out what I'm doing wrong?
OK, Since this question got interest near to none, according to view count, here is, briefly, the way I managed (hopefully) to resolve the problem (Please, correct me if you know more)
Verify modules' versions compatibility
According to one of the commenters in this SO question, not all (even latest) versions are compatible with each other. For example:
Hibernate Search 5.5 works with Hibernate ORM 5.0.x and 5.1.x (NOT
with 5.2.x), and with Apache Lucene 5.3.x, 5.4.x and 5.5.x (Not 6.0)
Stated by: Sanne
This is not a fix to this particular problem, but might save from other issues
Create a FieldBridge for Composite Key implementing
TwoWayFieldBridge
public class ScanResultBridge implements TwoWayFieldBridge
Add annotation to Entity Class, specifying the implementation of Bridge
#FieldBridge(impl = ScanResultBridge.class)
private ScanResultKey id;
I'm new to spring-roo and I want to generate and use my on ids for database entries in a mysql database instead of the auto-generated ids. And I'm not sure how to do this. The only related post I found here is this one:
How can I provide my own #id field using Spring Roo and JPA
But this post is now four years old and I'm using spring roo 1.3.2 instead of 1.1.0 so maybe something changed in the meantime.
So the generated code by spring roo in the test_Roo_Jpa_Entity.aj is:
privileged aspect test_Roo_Jpa_Entity {
declare #type: test: #Entity;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long test.id;
This is also what I see in the database. The id of a new entry is autogenerated and this is something I want to avoid.I played around with the --identifierField or --identifierColumn commands in spring roo but so far without any success. But I'm not sure how to use these commands.
Thank you very much for your help in advance!
EDIT 1:
Code for persit my Entity:
String[] split = line.split(";"); Long TEST_ID = Long.valueOf(split[0]);
String TEST_NAME = split[1]; TEST test = new TEST(); test.setName(TEST_NAME);
test.setId(TEST_ID); test.persist()
I think you have to move this part from your aspectJ file to your java Entity file.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long test.id;
To do so, you have to mark the line private Long test.id; and right click. Then you have to click on AspectJ Refactoring and Push In. This part should now be moved in your Java class.
Then change the strategy to #GeneratedValue(strategy = GenerationType.IDENTITY)
Now you should be able to create your own Id's. Sure your Database should also accept this.
I made a NamedQuery that works but I have multiple error markers in eclipse. Now my query might not be legal, an answer of so (see comments) told me it wasn't possible to do what I intended to do in jpa. So, since I managed to do it anyway and I don't really have a clue why it works: my question is what are the underlying risks of using this :
query = "SELECT t FROM Thethread t LEFT JOIN FETCH t.threadVotes tv ON tv.user1=:currentUser ORDER BY t.datePosted DESC"
Under on:
JOIN FETCH expressions cannot be defined with an identification
Under :currentUser:
Input parameters can only be used in the WHERE clause or HAVING clause of a query.
I didn't manage to get the result I want without it. Which is :
Get the newest Thethread
Get only the current user vote in its collection.
If you know how to do that, please, be my guest.
The entities are as such :
public class Thethread implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long idthread;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "date_posted")
private Date datePosted;
private int downvotes;
private int upvotes;
// bi-directional many-to-one association to ThreadVote
#OneToMany(mappedBy = "thethread")
private List<ThreadVote> threadVotes;
}
public class ThreadVote implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id_votes_thread")
private int idVotesThread;
private int vote;
// bi-directional many-to-one association to Thethread
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "thread")
private Thethread thethread;
// bi-directional many-to-one association to User
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "from_user")
private User user1;
}
Your query is correct JPQL according to JPA 2.1 (JavaEE 7). Eclipselink supports it and other providers should too, if they support 2.1 version of JPA.
The operator ON with JOIN is new with this latest JPA version, it was not present in neither JPA 2.0 (JavaEE 6) nor in older JPA 1 versions.
Here is more info from EclipseLink wiki. The wiki states that Eclipselink implements ON operator and that it is in draft JPA 2.1. I checked also that it is also in final JPA 2.1 specification - and it is there.
In order to use your query, you just need to ensure that your environment/application server supports JPA 2.1 (e.g. application server should support Java EE 7, such as Glassfish 4 or WildFly 8+)
It is not a problem that your IDE (Eclipse) gives warnings until your query works. Eclipse probably does not support JPA 2.1 syntax or your project must be somehow configured to support JPA 2.1 and not older versions of JPA. Try to look into project properties, under project facets, and ensure you have JPA in version 2.1
My JPA/Hibernate odyssey continues...
I am trying to work around this issue, and so I have had to define primitive #Ids in my class that uses 3 entity fields as a composite key. This seems to get me a bit further, but now I'm getting this when persisting:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.example.model.LanguageSkill.stafferId
Here's my composite class:
public class LanguageSkill implements Serializable
{
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "Staffer_ID")
private Long stafferId;
#Id
#ManyToOne(cascade = CascadeType.ALL)
#MapsId(value = "stafferId")
private Staffer staffer;
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "Language_ID")
private Long languageId;
#ManyToOne
#MapsId(value= "languageId")
private Language language;
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "Language_Proficiency_ID")
private Long languageProficiencyId;
#ManyToOne
#MapsId(value= "languageProficiencyId")
private LanguageProficiency languageProficiency;
}
I do have proper getters and setters (IDE-generated) for both the primitives as well as the entities.
Here are my libs. I'm not totally convinced that I'm using a compatible set of persistence libraries (references to a cookbook detailing how to properly mix-and-match these would be highly appreciated.)
Hibernate 3.5.6-SNAPSHOT
hibernate-jpamodelgen 1.1.0.CR1
hibernate-validator 3.1.0.GA
MySQL 5.1.6
jsr250-api 1.0
javax.validation validation-api 1.0.0.GA
Wow, it's frustrating. 3 days now full time trying to solve various issues like this just for basic ORM. I feel defective. :-(
It seems a correct code. I had problem with this exception when I used Blob[]
#Lob
#Column(name="DOCUMENTO",nullable=false)
private Blob[] documento;
But changing by Byte[], I solved this problem.
I have only a occurrence, looking Oracle data types, I have seen this LONG is Character data of variable length (A bigger version the VARCHAR2 datatype).
I assume that your ID is a Integer....Why not change Long by Integer? You must remember that it only accepts primitive types.
This is my code and it works fine:
#Id
#SequenceGenerator(sequenceName="SQ_DOCUMENTO",name="seqDocumento")
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seqDocumento")
private Integer idDocumento;
I use Hibernate 3.5.6-final, Spring 3.0.4, Junit 4 and Oracle 11g.
You have to remove the #GeneratedValue annotations.