I am migrating an ejb 2 application to ejb 3.1. Both technologies will have to coexist for a while. One of my entity beans looks like this:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
#Entity
#Table(name = "migracao_jsf")
#NamedQueries({
#NamedQuery(name = "migracao_query", query = "select p from MigracaoJsf p")
})
public class MigracaoJsf implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Column(name = "name")
#Id
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
On the deployment logs in jboss 6.1 I can see that the entity was deployed.
[AnnotationBinder] Binding entity from annotated class: myclass.MigracaoJsf
But I can't find the log for the query parsing. And when I try to call it I get a query not found exception. Why is the entity deployed correctly and the query not parsed?
Thanks
Kelly
You should be able to call the query using the following code:
EntityManager em;
// em is created sonehow
TypedQuery<MigracaoJsf> q = em.createNamedQuery("migracao_query", MigracaoJsf.class);
Also it is common practice to prefix the named queries with the class name since query names must be unique. Thus a query to get an entity by its name should be named Entity.GetByName.
Related
I have a JSF projekt using EclipseLink and OmniPersistence. Everything is working fine, I define the entities as follows:
import javax.persistence.Entity;
import org.omnifaces.persistence.model.GeneratedIdEntity;
#Entity
public class PeterOPeter extends GeneratedIdEntity<Long> {
private static final long serialVersionUID = 1L;
}
and
import javax.persistence.Entity;
import org.omnifaces.persistence.model.GeneratedIdEntity;
#Entity
public class PeterOPeter extends TimestampedEntity<Long> {
private static final long serialVersionUID = 1L;
}
So the following columns will be generated:
created
lastModified
id
I reached 23 different entities, no problem. Then I add another entity so it will be 24, a problem occurs. When I load an already persisted entity all generated columns (created, lastModified, id) are suddenly null. All other colums are correct. When I comment any of the entities so I go back to 23, everythings works again. Wow this is strange. Does anyone know if there is a limit on how many entities can be handle via OmniPersistence library?
Im using a findBy method in a interface that extends PagingAndSortingRepository. This method is:
public List<MyType> findByClassification(String classification);
When I invoke this method (myObject.findByClassification("A")), it returns all values and not only records filtered by classification "A".
The class model:
package mypackage;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "mytype")
public class MyType implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private String name;
private String classification;
//getters and setters
}
Other find methods work fine:
findByClassificationAndName_StartingWith
findByName
These methods return only filtered records and not all records in table.
Any idea?
Thanks!
In my Application, I have 2 Classes:
- Group
- Model
and one base class Element.
I use the single table strategy to persist these models. (strategy = InheritanceType.SINGLE_TABLE). Thus a column dtypeis created in my table.
I'm now trying to sort my pages based on this type:
find.where().disjunction()
.add(Expr.ilike("name", "%" + filter + "%"))
.orderBy("dtype asc, name asc," + sortBy + " " + order).findList()
But this throws an Exception, that dtype cannot be found.
How can I sort based on the type?
Thanks!
Sample base model can look like:
package models.db;
import play.db.ebean.Model;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(name = "content")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "dtype", discriminatorType = DiscriminatorType.STRING)
#DiscriminatorValue("content")
public abstract class Content extends Model {
#Id
public Long id;
#Column(name = "dtype", insertable = false, updatable = false)
public String dtype;
public static Finder<Long, Content> find = new Finder<>(Long.class, Content.class);
public String title;
public Date created = new Date();
public Date modified = new Date();
}
Then you can extend it like:
package models.db;
import javax.persistence.*;
#Entity
#DiscriminatorValue("news")
public class News extends Content {
#Id
public Long id;
public static Finder<Long, News> find = new Finder<>(Long.class, News.class);
public String newsSource;
}
or
package models.db;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
#Entity
#DiscriminatorValue("post")
public class Post extends Content {
#Id
public Long id;
public static Finder<Long, Post> find = new Finder<>(Long.class, Post.class);
public Date publishDate;
}
So you can choose all contents via:
List<Content> contents = Content.find.where().orderBy("dtype ASC").findList();
Of course these objects will have only shared fields: id, dtype, title, created and modified, for getting i.e. (News) newsSource or (Post) publishDate you need to get these objects with their own finders i.e. using id value from general Content query.
I have a Spring MVC based Java project. This project uses hibernate for the ORM. I am also using Eclipse Kepler as an IDE. I have a question about the Model portion of my project. All of the .java files that I have that are the Model files have an equivalent named file that ends in an underscore. These equivalent files ending in the underscore were automatically generated "I think by the IDE". I have no idea why these files got generated and what their purpose is. Can someone shed some light on this and point me in the right direction? I feel this is either an incorrect IDE setting that is causing them to get generated or is being generated due to some configuration setting that I have within my project.
For instance I have a User.java and a User_.java file. I wrote the User.java but not the User_.java. The User_.java was generated automatically. The code for each of these files is below, the first block is the User_.java that was generated automatically.
package com.bah.iaat.model.data;
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
#Generated(value="Dali", date="2014-04-03T23:00:06.698-0400")
#StaticMetamodel(AnalyticAgenda.class)
public class AnalyticAgenda_ {
public static volatile SingularAttribute<AnalyticAgenda, Integer> id;
public static volatile SingularAttribute<AnalyticAgenda, String> name;
public static volatile SingularAttribute<AnalyticAgenda, String> desc;
public static volatile SingularAttribute<AnalyticAgenda, Integer> userGroupId;
public static volatile SingularAttribute<AnalyticAgenda, String> flag;
}
The next block of code is the code that I wrote:
package com.bah.iaat.model.data;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#NamedQueries({#NamedQuery(name = "SelectAllUsers",query = "Select u from User u"),
#NamedQuery(name = "SelectUserByName",query = "Select u from User u where u.name =:uName"),
#NamedQuery(name = "findUserByIdentifier",query = "Select u from User u where u.name =:pId"),
#NamedQuery(name = "findUserIdByName",query = "select u.id from User u where u.name =:pName"),
#NamedQuery(name = "findUserByName",query = "select u from User u where u.name =:pName")})
#Entity
#Table(name="USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="USER_ID")
private Integer id;
#Column(name="USER_NAME", unique=true)
private String name;
#Column(name="LAST_LOGIN")
private Date lastLogin;
#ManyToOne
#JoinColumn(name="USER_GROUP_ID" )
private UserGroup userGroup;
public User() {}
public User(String name, UserGroup userGroup, Date lastLogin){
this.name = name;
this.userGroup = userGroup;
this.lastLogin = lastLogin;
}
.....
}
These classes constitute the metamodel of your persistence context. They are used when you use the JPA2 Criteria API, in order to create type-safe queries, based on identifiers instead of Strings. For example:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> from = query.from(Person.class);
query.where(criteriaBuilder.equal(person.get(Person_.name), "Doe"));
Using Person_.name instead of "name" guarantees that you're using a field that exists, and makes sure you'll get a compilation error instead of a runtime error if you rename the field name to lastName, for example.
Suppose I have the following simple Customer/Order implementation:
A record of customers defined by a Customer class.
Each customer can have multiple orders defined by an Order class.
Drawing on the explanation of Transparent Indirection from here and Container Policies from here my understanding of these concepts EclipseLink is as follows:
Transparent Indirection allows me to say
Customer customer = Customer.getCustomerById(1);
Set<Order> orders = customer.getOrders();
Two points to note are:
Indirection allows lazy loading of attributes so a customer's orders are only fetched from the DB on line 2, not line 1.
I can treat the orders of a customer as a Set (or Collection or List or Map) of objects of type Order.
The Container Policy tells to EclipseLink which actual class should be used for the Set and it should therefore implement Set in the example above.
That is my understanding of Transparent Indirection and Container Policies in EclipseLink.
I am seeing the following error when I try to access the database:
Exception [EclipseLink-148] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The container policy [CollectionContainerPolicy(class org.eclipse.persistence.indirection.IndirectSet)] is not compatible with transparent indirection.
Mapping: org.eclipse.persistence.mappings.OneToManyMapping[orders]
Descriptor: RelationalDescriptor(my.model.Customer --> [DatabaseTable(Customer)])
I'm sure I have an error in my code somewhere which I am trying to debug but I didn't specify the CollectionContainerPolicy mentioned in the error so I assume org.eclipse.persistence.indirection.IndirectSet is the default. But if I'm using the default policy then I'm not sure what the cause of this error may be or which policy I should be using.
For now, I'd just like to know if my understanding of Transparent Indirection and Container Policies as I mentioned above is correct.
If it is correct I'm probably missing something relatively small in my code (an invocation or configuration option etc.) but if I'm not understanding the concepts then clearly I need to do more research first.
Customer model
package my.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* The persistent class for the customer database table.
*
*/
#Entity
#Table(name=Customer.TBL_NAME)
#NamedQueries({
#NamedQuery(name=Customer.QRY_BY_NAME,query="Select object(a) from Customer a where " +
"a.name=:" + Customer.PRM_NAME),
#NamedQuery(name=Customer.QRY_ALL, query="select object(a) from Customer a")
})
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
// Table specific onstants
public static final String TBL_NAME = "Customer";
public static final String QRY_BY_NAME = TBL_NAME + ".byName";
public static final String QRY_ALL = TBL_NAME + ".all";
public static final String PRM_NAME = "name";
private int id;
private String name;
private Set<Order> orders;
public Customer() {
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//bi-directional many-to-one association to Order
#OneToMany(mappedBy="customer")
public Set<Order> getOrders() {
return this.orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}
Order model
package my.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* The persistent class for the order database table.
*
*/
#Entity
#Table(name=Order.TBL_NAME)
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
// Table constants
public static final String TBL_NAME = "Order";
private int id;
private Customer customer;
public Order() {
}
#Id
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
//bi-directional many-to-one association to Customer
#ManyToOne
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
Your understanding is correct, but shouldn't be needed as this isn't something you need to configure when using JPA. EclipseLink will determine the collection policy and implementation to use based on the type of the property and the lazy/eager setting, and it seems to be doing so correctly. The exception is thrown in error, probably due to classloader issues so that the classloader used for init isn't the one used to validate against, but I don't know how that could happen. You will need to look at the environment this is running in as the exception itself is just a symptom