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.
Related
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 am new to Open JPA and I am migrating my application DB services from JPA with Hibernate as vendor provider to JPA with OpenJPA as vendor Provider. Everything is fine, but I am not able to migrate my repositories. I am getting below error:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property find found for
type com.entities.LevelPossibilityData
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:271)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:245)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:72)
Here is my entity:
package com.entities;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import java.lang.reflect.Field;
#Entity
#Table(name = "LEVEL_POSSIBILITY_DATA", schema = "DEV")
#NamedQueries({
#NamedQuery(name = "LevelPossibilityData.findAllPossibilityGenIds", query = "SELECT distinct possibilityData.levelPossibilityGenId FROM LevelPossibilityData possibilityData where possibilityData.userCode is not null and possibilityData.possibilityType=?1 order by possibilityData.levelPossibilityGenId asc")})
public class LevelPossibilityData implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "LEVEL_SEQ_ID")
private BigDecimal levelSeqId;
#Column(name = "LEVEL_USER_CODE")
private String userCode;
#Column(name = "LEVEL_USER_POSSIBILITY_TYPE")
private String possibilityType;
#Column(name = "LEVEL_POSSIBILITY_GENERATOR_ID")
private String levelPossibilityGenId;
}
and my Repository:
package com.dao;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.entities.LevelPossibilityData;
public interface LevelPossibilityDataRepository<ID extends Serializable> extends JpaRepository<LevelPossibilityData, Serializable> {
public List<LevelPossibilityData> findAllPossibilityGenIds(String possibilityType);
}
Can you please help me out in rectifying this error?
I was able to solve the issue by removing Named Queries from entity. I introduced queries directly into Repository by using #Query annotation.
Just one catch, if you are using openJPA and trying to use #Query in Repository, try to use full path of the entities used e.g.
use "com.entities.LevelPossibilityData" instead of "LevelPossibilityData" in your query i.e. your query should be "select level from com.entities.LevelPossibilityData level" instead of "select level from LevelPossibilityData level".
I hope this explaination will be helpfull. Thanks everybody for devoting time on this.
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
I actually have a problem with JPA. He is complaining about one
of my Entities:
javax.persistence.RollbackException: Exception [EclipseLink-6023] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryException
Exception Description: The list of fields to insert into the table [DatabaseTable(TBL_SPJ_CAST_MOVIE)] is empty. You must define at least one mapping for this table.
After some researching i found out that this Exception appears when
there are no columns defined in the Entity classe because ofcourse
you cant insert Data into an empty Table.
However i have actually two columns defined in my Entity. One for the id
and one for a foreign key to a m:n table:
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity
#Table(name="TBL_SPJ_CAST_MOVIE")
public class CastMovie implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="CAST_MOVIE_ID", unique=true)
private int castID = 0;
#ManyToMany(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinTable(name="TBL_SPJ_CAST_ROLE", joinColumns={#JoinColumn(name="CAST_MOVIE_ID")}, inverseJoinColumns={#JoinColumn(name="ROLE_ID")})
private List<Role> roles = null;
public CastMovie() {}
public int getCastID() {
return castID;
}
public void setCastID(int castID) {
this.castID = castID;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
So whats the point of this Error? All Data coming from a xml file so i cant
put in more columns (if thats the problem).
EDIT:
Here is the structure of the four tables involved in this problem:
One Movie has one Cast -> Relationship One to One
Many Casts have many Rols -> Relationship Many to Many
I had the same problem.
Set the GenerationType of id field to GenerationType.TABLE and it will do the trick.
Also read this
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.