https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/
a quick reminder to myself:
if Post -> PostComment is a Unidirectional association (Post has a List<PostComments; but PostComment has no reference to Post),
then the insertion of each PostComment is done in two phases (INSERT + UPDATE who sets the parentId on the child table).
For this reason, the parentId column CANNOT BE DECLARED AS NOT NULL.
I don't like that.... ultimately that column should NEVER be null...
On the other hand, if you setup a full bidirectional relationship, only ONE insert is done, and you can keep parentId as NOT NULL.
To achieve that, you must explicitely set the Post attribute on the PostComment entity, before you persist/merge (I think, at least)
Showing posts with label JPA. Show all posts
Showing posts with label JPA. Show all posts
Thursday, November 7, 2019
Thursday, May 16, 2019
Jooq and QueryDSL as alternatives to JPQL, Panache,
HQL (and JPQL) both suck because they are not statically typed..."lack of type safety and absence of static query checking" "concatenation of strings which is usually very unsafe "
"Criteria Query API ended up very verbose and practically unreadable. "
https://www.jooq.org/
"jOOQ generates Java code from your database and lets you build type safe SQL queries through its fluent API. "
So this is no ORM framework, it uses your DB as it is, it simply allows you to write safer SQL queries directly in a fluent Java API. No Hocus-Pocus, it's a 1-to-1 mapping between DB and Java.
Here some examples https://www.jooq.org/doc/3.11/manual-single-page/#jooq-in-7-steps
http://www.querydsl.com/
how to use it https://www.baeldung.com/querydsl-with-jpa-tutorial and https://www.baeldung.com/intro-to-querydsl
If you want to use Native SQL or JPQL in Spring: https://www.baeldung.com/spring-data-jpa-query
This is the horribly verbose JPA Criteria API https://www.baeldung.com/hibernate-criteria-queries
" the main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API."
"Criteria Query API ended up very verbose and practically unreadable. "
https://www.jooq.org/
"jOOQ generates Java code from your database and lets you build type safe SQL queries through its fluent API. "
So this is no ORM framework, it uses your DB as it is, it simply allows you to write safer SQL queries directly in a fluent Java API. No Hocus-Pocus, it's a 1-to-1 mapping between DB and Java.
Here some examples https://www.jooq.org/doc/3.11/manual-single-page/#jooq-in-7-steps
http://www.querydsl.com/
how to use it https://www.baeldung.com/querydsl-with-jpa-tutorial and https://www.baeldung.com/intro-to-querydsl
If you want to use Native SQL or JPQL in Spring: https://www.baeldung.com/spring-data-jpa-query
This is the horribly verbose JPA Criteria API https://www.baeldung.com/hibernate-criteria-queries
" the main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API."
Monday, May 6, 2019
Panache as a wrapper for Hibernate
https://quarkus.io/guides/hibernate-orm-panache-guide
https://developers.redhat.com/courses/quarkus/effective-data-hibernate-and-panache-quarkus/
The product seems very well conceived, it really streamlines your JPA code.
One more aspect where the Java world has completely screwed up, is the 20 different ways you can implement DB queries....
ah if only ORM had been embedded into the language from the beginning, we would be dealing with a single persistence framework.
https://developers.redhat.com/courses/quarkus/effective-data-hibernate-and-panache-quarkus/
The product seems very well conceived, it really streamlines your JPA code.
One more aspect where the Java world has completely screwed up, is the 20 different ways you can implement DB queries....
ah if only ORM had been embedded into the language from the beginning, we would be dealing with a single persistence framework.
Saturday, April 7, 2018
H2 autogenerating unique IDs from Sequence
if you have annotated the ID with
and declared the ID as
this is not enough... you will get this when you try to insert a new record:
Solution is:
CREATE SEQUENCE VOCABULARY_SEQUENCE_ID START WITH (select max(ID) + 1 from VOCABULARY);
(this allows me to prepopulate the VOCABULARY with static values, and initialize the sequence accordingly)
and in Java
Why in 2018 such common things have to be still so complicated, no clue, something is really going wrong in the Java world... maybe using Spring it's only a matter of 1 annotation... no clue...
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Entity;
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "ID"), name = "VOCABULARY")
public class Vocabulary implements Serializable {
@Id
@GeneratedValue
private Long id;
and declared the ID as
CREATE TABLE "VOCABULARY" (
"ID" NUMBER(10,0) NOT NULL
...
)
CREATE UNIQUE INDEX "VOCABULARY_UNIQ_ID" ON "VOCABULARY" ("ID") ;
ALTER TABLE "VOCABULARY" ADD PRIMARY KEY ("ID");
this is not enough... you will get this when you try to insert a new record:
org.h2.jdbc.JdbcSQLException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readSequence(Parser.java:5970)
at org.h2.command.Parser.readTerm(Parser.java:3131)
at org.h2.command.Parser.readFactor(Parser.java:2587)
at org.h2.command.Parser.readSum(Parser.java:2574)
at org.h2.command.Parser.readConcat(Parser.java:2544)
at org.h2.command.Parser.readCondition(Parser.java:2370)
at org.h2.command.Parser.readAnd(Parser.java:2342)
at org.h2.command.Parser.readExpression(Parser.java:2334)
at org.h2.command.Parser.parseCall(Parser.java:4854)
at org.h2.command.Parser.parsePrepared(Parser.java:382)
at org.h2.command.Parser.parse(Parser.java:335)
at org.h2.command.Parser.parse(Parser.java:307)
at org.h2.command.Parser.prepareCommand(Parser.java:278)
at org.h2.engine.Session.prepareLocal(Session.java:611)
at org.h2.server.TcpServerThread.process(TcpServerThread.java:271)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:165)
at java.lang.Thread.run(Thread.java:748)
at org.h2.engine.SessionRemote.done(SessionRemote.java:624)
at org.h2.command.CommandRemote.prepare(CommandRemote.java:68)
at org.h2.command.CommandRemote.(CommandRemote.java:45)
at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.java:494)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1203)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:676)
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.doPrepareStatement(BaseWrapperManagedConnection.java:757)
at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.prepareStatement(BaseWrapperManagedConnection.java:743)
at org.jboss.jca.adapters.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:454)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$1.doPrepare(StatementPreparerImpl.java:87)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
Solution is:
CREATE SEQUENCE VOCABULARY_SEQUENCE_ID START WITH (select max(ID) + 1 from VOCABULARY);
(this allows me to prepopulate the VOCABULARY with static values, and initialize the sequence accordingly)
and in Java
@Id @SequenceGenerator(name= "VOCABULARY_SEQUENCE", sequenceName = "VOCABULARY_SEQUENCE_ID", initialValue=1, allocationSize = 1) @GeneratedValue(strategy=GenerationType.AUTO, generator="VOCABULARY_SEQUENCE") private Long id;
Why in 2018 such common things have to be still so complicated, no clue, something is really going wrong in the Java world... maybe using Spring it's only a matter of 1 annotation... no clue...
Friday, April 6, 2018
Eclipse generate JPA entities from DB
Unfortunately there doesn't seem to exist a tool to generate JPA Entities directly from SQL. Weird!
So you have to start by populating a real schema.
Create a Java project
Configure "Targeted Runtimes" with "Wildfly 11 Runtime"
Configure Project, Facets, and select JPA (ignore the "further configuration available")
Right-click on Project, you should see "JPA Tools", "Generate Entities from tables"
When I was young I was thinking of 2017 as the age of teletransportation and instant cure for all diseases. Instead it's the age of wasting hours for a Maven configuration. I bet the Cro-Magnon were more technologically savvy than the Maven folks.
So you have to start by populating a real schema.
Create a Java project
Configure "Targeted Runtimes" with "Wildfly 11 Runtime"
Configure Project, Facets, and select JPA (ignore the "further configuration available")
Right-click on Project, you should see "JPA Tools", "Generate Entities from tables"
When I was young I was thinking of 2017 as the age of teletransportation and instant cure for all diseases. Instead it's the age of wasting hours for a Maven configuration. I bet the Cro-Magnon were more technologically savvy than the Maven folks.
Labels:
JPA
Saturday, November 18, 2017
JPA, Hibernate, Dali and the Metamodel
When building Query criterias, you want to avoid using the String "email" to identify an Entity field... the day you change the field "email" into "mailaddress", your code still compiles but breaks in PROD... ugly... unless you wrote tests... but I prefer when it breaks during compile!
So you must use https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/querycriteria.html "the static form of metamodel reference", that is using an automatically generated class
https://stackoverflow.com/questions/3037593/how-to-generate-jpa-2-0-metamodel
Example:
and its metamodel
To achieve this in Eclipse: Project/Properties and then:

The multitude of very complicated options (in Maven for instance) to achieve the same EASY result is just one more evidence of the very pathetic state of IT in 2017.... a huge spread of technologies and product to achieve really basic results.... the notion of metadata associated to persistence was around already 25 years ago, it's sad to see that we still don't have proper engineering and consolidated practice.
At this point I can write my logic like this:
Of course there are much easier ways to achieve the same result, like JPQL https://en.wikipedia.org/wiki/Java_Persistence_Query_Language
So you must use https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/querycriteria.html "the static form of metamodel reference", that is using an automatically generated class
https://stackoverflow.com/questions/3037593/how-to-generate-jpa-2-0-metamodel
Example:
package org.pierre.calories.entities;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* The persistent class for the USERS database table.
*
*/
@Entity
@Table(name="USERS")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private String userid;
private BigDecimal expectedcalperday;
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public User() {
}
public User(String userid, BigDecimal expectedcalperday) {
super();
this.userid = userid;
this.expectedcalperday = expectedcalperday;
}
public String getUserid() {
return this.userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public BigDecimal getExpectedcalperday() {
return this.expectedcalperday;
}
public void setExpectedcalperday(BigDecimal expectedcalperday) {
this.expectedcalperday = expectedcalperday;
}
}
and its metamodel
package org.pierre.calories.entities;
import java.math.BigDecimal;
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
@Generated(value="Dali", date="2017-11-18T11:02:45.198+0100")
@StaticMetamodel(User.class)
public class User_ {
public static volatile SingularAttribute<User, String> userid;
public static volatile SingularAttribute<User, BigDecimal> expectedcalperday;
public static volatile SingularAttribute<User, String> email;
}
To achieve this in Eclipse: Project/Properties and then:
The multitude of very complicated options (in Maven for instance) to achieve the same EASY result is just one more evidence of the very pathetic state of IT in 2017.... a huge spread of technologies and product to achieve really basic results.... the notion of metadata associated to persistence was around already 25 years ago, it's sad to see that we still don't have proper engineering and consolidated practice.
At this point I can write my logic like this:
package org.pierre.calories.database;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import org.pierre.calories.entities.Meal;
import org.pierre.calories.entities.User;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
@ApplicationScoped
public class CaloriesRepository {
@Inject
private EntityManager em;
public Meal findMealById(Long id) {
return em.find(Meal.class, id);
}
public User findUserById(Long id) {
return em.find(User.class, id);
}
public User findUserByEmail(String email) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = cb.createQuery(User.class);
Root<User> rootUser = criteria.from(User.class);
CriteriaQuery<User> select = criteria.select(rootUser);
//OLD SCHOOL CriteriaQuery<User> emailresult = select.where(cb.equal(rootUser.get("email"), email));
CriteriaQuery<User> emailresult = select.where(cb.equal(rootUser.get(User_.email), email));
return em.createQuery(emailresult).getSingleResult();
}
}
Of course there are much easier ways to achieve the same result, like JPQL https://en.wikipedia.org/wiki/Java_Persistence_Query_Language
Saturday, October 28, 2017
Setting up Maven to retrieve ojdbc8.jar
googling around in StackOverflow there is a huge variety of approaches to this very common problem: you must add the artifact to your build, but it's not available in Maven Central.... what to do?
Some resort to downloading it manually and deploying it to the local Maven repo. Some even include the file in their WEB-INF/lib folder in their SCM project. Some use some third party public repositories (like Atlassian, code.lds.org, ... ) who graciously host these artifacts.... all fine when you play on your PC, but in a serious company with strict security control all this would not be allowed. Some folks simply cowboy-style put it somewhere in their HD and add the external JAR to Eclipse.... what happens next, they don't really care, as long as it works on their machine.
Oracle hosts these artifacts in their Public Oracle Maven repository, but you need to authenticate yourself (for which reason, it's totally obscure to me!)
https://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9016 here how to setup maven to connect to the Oracle repo (basically: in settings.xml you have to declare the server maven.oracle.com authenticating with your user, the in your pom.xml you must declare a rerpository with id matching this maven.oracle.com server, then a pluginRepository with id again maven.oracle.com. At this point you can declare the dependency
This post explains it in a lot of detail https://blogs.oracle.com/dev2dev/get-oracle-jdbc-drivers-and-ucp-from-oracle-maven-repository-without-ides
To make things much more complicated, the repository is not browsable https://maven.oracle.com/com/oracle/ojdbc8/ ... how to determine it content, no clue!
See also https://stackoverflow.com/questions/9898499/oracle-jdbc-ojdbc6-jar-as-a-maven-dependency] and https://stackoverflow.com/questions/1074869/find-oracle-jdbc-driver-in-maven-repository
https://mvnrepository.com/artifact/com.oracle/ojdbc6/12.1.0.1-atlassian-hosted to get ojdbc6.jar from maven (atlassian hosted!)
https://developer.atlassian.com/docs/advanced-topics/working-with-maven/atlassian-maven-repositories to configure atlassian repo in pom.xml
IMPORTANT: when running in Eclipse, make sure you are NOT using the Embedded installation of Maven while you are configuring an EXTERNAL Maven configuration.... this multiplicity of installations and configurations only makes the developer's life more miserable.... IMHO it's better to have an independent, external, universal installation rather than an embedded one.... again another major fuck-up in Eclipse design. Forget Eclipse, use Netbeans and Intellij.
CODE: a working pom.xml is available here https://github.com/vernetto/JavaMonAmour/tree/master/oracletest
Some resort to downloading it manually and deploying it to the local Maven repo. Some even include the file in their WEB-INF/lib folder in their SCM project. Some use some third party public repositories (like Atlassian, code.lds.org, ... ) who graciously host these artifacts.... all fine when you play on your PC, but in a serious company with strict security control all this would not be allowed. Some folks simply cowboy-style put it somewhere in their HD and add the external JAR to Eclipse.... what happens next, they don't really care, as long as it works on their machine.
Oracle hosts these artifacts in their Public Oracle Maven repository, but you need to authenticate yourself (for which reason, it's totally obscure to me!)
https://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9016 here how to setup maven to connect to the Oracle repo (basically: in settings.xml you have to declare the server maven.oracle.com authenticating with your user, the in your pom.xml you must declare a rerpository with id matching this maven.oracle.com server, then a pluginRepository with id again maven.oracle.com. At this point you can declare the dependency
<dependency> <groupId>com.oracle.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>12.2.0.1</version> </dependency>
This post explains it in a lot of detail https://blogs.oracle.com/dev2dev/get-oracle-jdbc-drivers-and-ucp-from-oracle-maven-repository-without-ides
To make things much more complicated, the repository is not browsable https://maven.oracle.com/com/oracle/ojdbc8/ ... how to determine it content, no clue!
See also https://stackoverflow.com/questions/9898499/oracle-jdbc-ojdbc6-jar-as-a-maven-dependency] and https://stackoverflow.com/questions/1074869/find-oracle-jdbc-driver-in-maven-repository
https://mvnrepository.com/artifact/com.oracle/ojdbc6/12.1.0.1-atlassian-hosted to get ojdbc6.jar from maven (atlassian hosted!)
https://developer.atlassian.com/docs/advanced-topics/working-with-maven/atlassian-maven-repositories to configure atlassian repo in pom.xml
IMPORTANT: when running in Eclipse, make sure you are NOT using the Embedded installation of Maven while you are configuring an EXTERNAL Maven configuration.... this multiplicity of installations and configurations only makes the developer's life more miserable.... IMHO it's better to have an independent, external, universal installation rather than an embedded one.... again another major fuck-up in Eclipse design. Forget Eclipse, use Netbeans and Intellij.
CODE: a working pom.xml is available here https://github.com/vernetto/JavaMonAmour/tree/master/oracletest
Friday, December 9, 2016
EntityManager and statement timeout
We spoke here about Statement Timeout to set on a Datasource http://www.javamonamour.org/2013/04/statement-timeout-on-datasource.html
If you use an EntityManager, you don't have access to the javax.sql.Statement object. This is the beauty of abstraction (sarcasm here): it prevents you from using the full power of the underlying technology, and it forces you to awkward acrobatics.
I would give a try to javax.persistence.query.timeout
http://stackoverflow.com/questions/24244621/set-timeout-on-entitymanager-query
https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/
see https://docs.oracle.com/javaee/6/api/javax/persistence/Query.html
but it works (actually, they told me it doesn't work AT ALL with WebLogic 12 and Eclipse JPA) only if you use Queries with EntityManager....
If you use an EntityManager, you don't have access to the javax.sql.Statement object. This is the beauty of abstraction (sarcasm here): it prevents you from using the full power of the underlying technology, and it forces you to awkward acrobatics.
I would give a try to javax.persistence.query.timeout
http://stackoverflow.com/questions/24244621/set-timeout-on-entitymanager-query
https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/
query.setHint("javax.persistence.query.timeout", 2000);
see https://docs.oracle.com/javaee/6/api/javax/persistence/Query.html
but it works (actually, they told me it doesn't work AT ALL with WebLogic 12 and Eclipse JPA) only if you use Queries with EntityManager....
Wednesday, May 2, 2012
Eclipse JPA, classpath needed
<classpathentry kind="lib" path="C:/Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar"/>
<classpathentry kind="lib" path="C:/Oracle/Middleware/modules/org.apache.openjpa_1.2.0.0_1-1-1-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="C:/Oracle/Middleware/wlserver_10.3/server/lib/wlthint3client.jar"/>
not only, but running from Eclipse you should put weblogic.jar in the BOOTSTRAP classpath...
terrible, really terrible...
and don't forget to put
property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.OraclePlatform"
in the persistence.xml
<classpathentry kind="lib" path="C:/Oracle/Middleware/modules/org.apache.openjpa_1.2.0.0_1-1-1-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="C:/Oracle/Middleware/wlserver_10.3/server/lib/wlthint3client.jar"/>
not only, but running from Eclipse you should put weblogic.jar in the BOOTSTRAP classpath...
terrible, really terrible...
and don't forget to put
property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.OraclePlatform"
in the persistence.xml
Saturday, April 28, 2012
Sample EntityManager usage in Java and Python WLST
In Eclipse, create a JDBC Connection
show view Data Source Explorer
new Connection Profile (enter parameters for your schema)
New JPA project
JPA Tools, Generate Entities from Tables
you should have a persistence.xml which contains
You can now code the client:
you will need to add the JDBC driver to the classpath, like
C:\bea1035\wlserver_10.3\server\ext\jdbc\oracle\11g\ojdbc5_g.jar
In WLST, just add to the classpath the location from which you can access classes and META-INF (where persistence.xml is located).... like the build\classes directory.
so the message is: you can easily use JPA in WLST and get rid of all that horrible pain of reading property files, by accessing directly a DB
show view Data Source Explorer
new Connection Profile (enter parameters for your schema)
New JPA project
JPA Tools, Generate Entities from Tables
you should have a persistence.xml which contains
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="ToplinkTest" transaction-type="RESOURCE_LOCAL"> <class>com.osb.reporting.WliQsReportAttribute</class> <class>com.osb.reporting.WliQsReportData</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe"/> <property name="javax.persistence.jdbc.user" value="DEV_SOAINFRA"/> <property name="javax.persistence.jdbc.password" value="DEV_SOAINFRA"/> <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/> </properties> </persistence-unit> </persistence>
You can now code the client:
package com.osb.reporting.client;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.osb.reporting.WliQsReportAttribute;
public class ReportingClient {
public static void main(String[] args) throws ClassNotFoundException {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ToplinkTest");
EntityManager em = emf.createEntityManager();
WliQsReportAttribute result = em.find(WliQsReportAttribute.class, "uuid:0e6fb58fc7c49289:5378b92d:134416bc5f5:-7fbe");
System.out.println(result.getMsgLabels());
Query fa = em.createQuery("select a from WliQsReportAttribute a");
List res = fa.getResultList();
for (Object el : res) {
System.out.println( ((WliQsReportAttribute)el).getMsgLabels());
}
}
}
you will need to add the JDBC driver to the classpath, like
C:\bea1035\wlserver_10.3\server\ext\jdbc\oracle\11g\ojdbc5_g.jar
In WLST, just add to the classpath the location from which you can access classes and META-INF (where persistence.xml is located).... like the build\classes directory.
package com.osb.reporting.client;
from javax.persistence import *
emf = Persistence.createEntityManagerFactory("CMBDModeling")
em = emf.createEntityManager()
q = em.createQuery("select envs from Nesoa2Env envs")
res = q.getResultList()
for i in res:
print i.envname
so the message is: you can easily use JPA in WLST and get rid of all that horrible pain of reading property files, by accessing directly a DB
Labels:
EntityManager,
JPA
Tuesday, April 5, 2011
org.hibernate.LazyInitializationException: failed to lazily initialize a collection
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: acme.domain.model.Bla.mumbles, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
Entity Bla contains a collection of Mumbles. The OneToMany annotation by default uses a LAZY loading approach.
If in your client layer you try to do a bla.getMumbles(), you get the exception LazyInitializationException. The session was closed in the EJB, and in the client you have only a detached entity.
To avoid the problem, in the EJB do a
bla.getMumbles().size();
(bla.getMumbles() is not enough!)
This will explicitly load ALL mumbles and the client will be happy.
Monday, March 14, 2011
ManyToOne, OneToMany, ManyToMany
http://download.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html
@ManyToOne(optional=false)
@JoinColumn(name="CUST_ID", nullable=false, updatable=false)
public Customer getCustomer() { return customer; }
http://download.oracle.com/javaee/6/api/javax/persistence/OneToMany.html
@OneToMany(cascade=ALL, mappedBy="customer")
public Set getOrders() { return orders; }
the first is always "me", the second is "the other"
ManyToOne means "there are many of me for one of them" -> hence I have only 1 of them, and he has a Set of me
OneToMany means "there is one of me for many of them" -> hence I have a Set of them
http://download.oracle.com/javaee/6/api/javax/persistence/ManyToMany.html
@ManyToMany
@JoinTable(name="CUST_PHONES")
public Set getPhones() { return phones; }
I have a Set of them, and they have a Set of me
@ManyToOne(optional=false)
@JoinColumn(name="CUST_ID", nullable=false, updatable=false)
public Customer getCustomer() { return customer; }
http://download.oracle.com/javaee/6/api/javax/persistence/OneToMany.html
@OneToMany(cascade=ALL, mappedBy="customer")
public Set
the first is always "me", the second is "the other"
ManyToOne means "there are many of me for one of them" -> hence I have only 1 of them, and he has a Set of me
OneToMany means "there is one of me for many of them" -> hence I have a Set of them
http://download.oracle.com/javaee/6/api/javax/persistence/ManyToMany.html
@ManyToMany
@JoinTable(name="CUST_PHONES")
public Set
I have a Set of them, and they have a Set of me
Labels:
JPA
com.arjuna.ats.internal.jta.transaction.arjunacore.inactive
Arjuna is the JBoss transaction manager
http://management-platform.blogspot.com/2008/11/transaction-timeouts-and-ejb3jpa.html
the entire stacktrace is:
11:13:43,774 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicActio
n_58] - Abort of action id a647bde:4e9:4d7de8ef:30 invoked while multiple threads active within it.
11:13:43,790 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.CheckedAct
ion_2] - CheckedAction::check - atomic action a647bde:4e9:4d7de8ef:30 aborting with 1 threads active!
11:13:44,274 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicActio
n_40] - Abort called on already aborted atomic action a647bde:4e9:4d7de8ef:30
11:13:44,337 FATAL [TechnicalExceptionHandler] Technical exception [7b2b91d6-ab3
f-4cb6-9bc1-3ae8302d44c5] occured:
java.lang.IllegalStateException: [com.arjuna.ats.internal.jta.transaction.arjuna
core.inactive] [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] The
transaction is not active!
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.c
ommitAndDisassociate(TransactionImple.java:1379)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.co
mmit(BaseTransaction.java:135)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTra
nsactionManagerDelegate.java:87)
at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java
:191)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInt
erceptor.java:95)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(Stateles
sInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(Authentic
ationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3Auth
enticationInterceptor.java:110)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterce
ptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(Asynchrono
usInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessCont
ainer.java:240)
at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessCont
ainer.java:210)
at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalPro
xy.java:84)
http://management-platform.blogspot.com/2008/11/transaction-timeouts-and-ejb3jpa.html
the entire stacktrace is:
11:13:43,774 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicActio
n_58] - Abort of action id a647bde:4e9:4d7de8ef:30 invoked while multiple threads active within it.
11:13:43,790 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.CheckedAct
ion_2] - CheckedAction::check - atomic action a647bde:4e9:4d7de8ef:30 aborting with 1 threads active!
11:13:44,274 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicActio
n_40] - Abort called on already aborted atomic action a647bde:4e9:4d7de8ef:30
11:13:44,337 FATAL [TechnicalExceptionHandler] Technical exception [7b2b91d6-ab3
f-4cb6-9bc1-3ae8302d44c5] occured:
java.lang.IllegalStateException: [com.arjuna.ats.internal.jta.transaction.arjuna
core.inactive] [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] The
transaction is not active!
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.c
ommitAndDisassociate(TransactionImple.java:1379)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.co
mmit(BaseTransaction.java:135)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTra
nsactionManagerDelegate.java:87)
at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java
:191)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInt
erceptor.java:95)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(Stateles
sInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(Authentic
ationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3Auth
enticationInterceptor.java:110)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterce
ptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(Asynchrono
usInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessCont
ainer.java:240)
at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessCont
ainer.java:210)
at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalPro
xy.java:84)
Wednesday, March 2, 2011
detached entity passed to persist
well, if your entity has already an ID, and you invoke
entitymanager.persist(bla)
Hibernate will think you are trying to persist an already existing entity, and he will react giving this stern and cryptic error message.
Just set the ID to null and you will smile again.
When mapping an entity to another, NEVER map the ID!
entitymanager.persist(bla)
Hibernate will think you are trying to persist an already existing entity, and he will react giving this stern and cryptic error message.
Just set the ID to null and you will smile again.
When mapping an entity to another, NEVER map the ID!
Labels:
JPA
Monday, February 14, 2011
JPA mapping boolean to CHAR(1) yes_no
After having googled around and found this and this, I have decided for the simplest possible solution: use a char in the Entity and expose it with a boolean getter/setter - anyway JPA uses "field" access to the Entity, so she is not disturbed by my setters and getters.
Incidentally all my boolean fields are NOT NULL, so I use directly a boolean rather than a Boolean.
It's a shame that JPA doesn't cover something so basic. Everybody knows that Oracle doesn't support a BOOLEAN data type; so I expect everyone is having the same problem.
private char sysparam = 'N';
public void setSysparam(boolean sysparam) {
this.sysparam = sysparam ? 'Y' : 'N';
}
public boolean getSysparam() {
return sysparam == 'Y';
}
Incidentally all my boolean fields are NOT NULL, so I use directly a boolean rather than a Boolean.
It's a shame that JPA doesn't cover something so basic. Everybody knows that Oracle doesn't support a BOOLEAN data type; so I expect everyone is having the same problem.
Labels:
JPA
Friday, February 11, 2011
JPA Entity: extending vs embedding
http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Example_of_an_Embeddable_object_annotations
JPA defines 2 annotations: @Embeddable and @Embedded
This is a great way to COMPOSE objects - rather than inheriting.
Suppose you have to incorporate in your entities several features:
tracking, logical deletion, id....
one solution is to stick all the co,,on features in a base abstract Entity.
The problem arises when not ALL Entities use ALL the features...; then you should introduce several base classes... this could soon become unmanageable.
The alternative is to Embed only the Embeddable entities that you want to incorporate.
The problem is that it's not easy to determine which Embeddable Entities are embedded in a given Entity.... while when using abstract classes or interfaces you can use instanceof.
JPA defines 2 annotations: @Embeddable and @Embedded
This is a great way to COMPOSE objects - rather than inheriting.
Suppose you have to incorporate in your entities several features:
tracking, logical deletion, id....
one solution is to stick all the co,,on features in a base abstract Entity.
The problem arises when not ALL Entities use ALL the features...; then you should introduce several base classes... this could soon become unmanageable.
The alternative is to Embed only the Embeddable entities that you want to incorporate.
The problem is that it's not easy to determine which Embeddable Entities are embedded in a given Entity.... while when using abstract classes or interfaces you can use instanceof.
Labels:
embeddable,
JPA
Wednesday, February 9, 2011
All you wanted to know about JPA
http://en.wikibooks.org/wiki/Java_Persistence
it's a really good source of information... I love wikified information, so easy to navigate.
it's a really good source of information... I love wikified information, so easy to navigate.
Labels:
JPA
Thursday, February 3, 2011
java.lang.IllegalStateException: EMF has not been initialized yet!
have you remembered to setup your JTA Datasource in the persistence.xml ? Remember to provide the JNDI name for the DS, not the logical name.
Is it pointing to a valid DS in WebLogic?
Probably the EntityManagerFactory didn't start because of invalid DS. Check the logs.
Thanks Dimitri for pointing this out :o)
Is it pointing to a valid DS in WebLogic?
Probably the EntityManagerFactory didn't start because of invalid DS. Check the logs.
Thanks Dimitri for pointing this out :o)
Labels:
JPA
Saturday, August 28, 2010
Eclipse JPA project broken when mavenized: Invalid content (no root node)
My Eclipse JPA project was broken once mavenized:
I get a message:
Invalid content (no root node)
I have had some allucinating time reading this
https://bugs.eclipse.org/bugs/show_bug.cgi?id=290929
How sad.... anyway I found a workaround to get rid of the message:
I copy META-INF/persistence.xml in all the source folders of my project (in my case, the src/test/java folder).
Long live Eclipse! Long live Maven! One day hopefully these products will be remembered as one of the biggest trash of history.... unfortunately these days we have to learn how to coexist with them, just like Iraqis learn to coexist with US Marines.
I get a message:
Invalid content (no root node)
I have had some allucinating time reading this
https://bugs.eclipse.org/bugs/show_bug.cgi?id=290929
How sad.... anyway I found a workaround to get rid of the message:
I copy META-INF/persistence.xml in all the source folders of my project (in my case, the src/test/java folder).
Long live Eclipse! Long live Maven! One day hopefully these products will be remembered as one of the biggest trash of history.... unfortunately these days we have to learn how to coexist with them, just like Iraqis learn to coexist with US Marines.
Labels:
eclipse,
JPA,
maven,
mavensucks
Saturday, July 17, 2010
JPA and primary key sequence generation
Nothing is easy...
I do:
create sequence GEO_MESSAGES_LOG_SEQ;
and I assign the primary key as "sequence generated".
This entails these annotations:
I immediately get this error:
Exception [TOPLINK-7027]
Exception Description: The sequence named [GEO_MESSAGES_LOG_SEQ] is setup incorrectly. Its increment does not match its pre-allocation size.
in @SequenceGenerator I add allocationSize=1
and things magically work... I suspect performance will not be great...
I do:
create sequence GEO_MESSAGES_LOG_SEQ;
and I assign the primary key as "sequence generated".
This entails these annotations:
@Id @SequenceGenerator(name="GEO_MESSAGES_LOG_ID_GENERATOR", sequenceName="GEO_MESSAGES_LOG_SEQ", allocationSize=1) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GEO_MESSAGES_LOG_ID_GENERATOR")
I immediately get this error:
Exception [TOPLINK-7027]
Exception Description: The sequence named [GEO_MESSAGES_LOG_SEQ] is setup incorrectly. Its increment does not match its pre-allocation size.
in @SequenceGenerator I add allocationSize=1
and things magically work... I suspect performance will not be great...
Labels:
JPA
Subscribe to:
Posts (Atom)