Could not determine type for: java.util.Map: JPA2 Map annotation - jpa

I use JPA in standalone mode. I have this error when i launch the persistenceManager:
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
I have test several work around grabbed around the net... no success.
Can you give me some clues ?
Could not determine type for: java.util.Map..................
for columns: [org.hibernate.mapping.Column(initRegisters)]
I have configured my mapping like this:
#ElementCollection(targetClass = Integer.class)
#MapKeyClass(InitRegister.class)
private Map<Integer, InitRegister> initRegisters = new HashMap<>();
What am i doing wrong ?
Thx in advance !

targetClass attribute of ElementCollection when applied to a map, refers to the type of the Map value - in your case, this is the InitRegister
On the other hand, #MapKeyClass refers to the type of the Map key, which is an Integer type.
So to fix your mistake, you just switch the types:
#ElementCollection(targetClass = InitRegister.class)
#MapKeyClass(Integer.class)
private Map<Integer, InitRegister> initRegisters;
You need not specify the targetClass and MapKeyClass if you are using generics.
So this one should be fine as well:
#ElementCollection
private Map<Integer, InitRegister> initRegisters;
Also, keep in mind that #ElementCollection is used only for basic types and embeddable types. If your InitRegister class happens to be an entity type, then you should not use #ElementCollection. You should use collection valued relationship mappings, either #OneToMany or #ManyToMany.

Solution Found:
Actually, all change was done on the declaration. I tried to add annotation on the getters field and..... it works.
Don't know why. I know that is a good practice but not mandatory.
Prob solved.

Related

Add entity to the context without knowing the type

Is it possible to add a POCO entity to the object context without knowing the type?
For example, here I'm adding an employee...
context.Employ.Attach(employer);
Is it possible to do something like this...
context.Attach(employer);
This works...
context.Set(entity.GetType()).Attach(entity);
You may be able to use the Set property of your context. For example:
var entityType = employer.GetType();
context.Set(entityType).Attach(employer);

Spring Data JPA repository methods don't recognize property names with underscores

I have underscores in the entity property names, and when Spring tries to create the JPA repository implementation, it results in an exception trying to resolve the name of the property.
Entity:
#Entity
public class Student {
#Id
private String s_id;
private String s_name;
...
}
Repository:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findByS__name(String name);
}
Exception:
org.springframework.data.mapping.PropertyReferenceException:
No property s found for type Student
It is said here http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
If your property names contain underscores (e.g. first_name) you can
escape the underscore in the method name with a second underscore. For
a first_name property the query method would have to be named
findByFirst__name(…).
I just did as document said, but I still got the exception.
I dont want write #Query by myself, and I need underscore in my property name, how to fix this problem?
I use Spring data jpa 1.8.0.RELEASE + hibernate 4.3.9.Final
Avoid using underscores in the entity property names if you have control over the property naming. This will resolve your repository woes, and will result in a cleaner code-base. Developers dealing with the code after you will thank you.
Note, it's not just my opinion: Spring specifically discourages using underscores.
As we treat underscore as a reserved character we strongly advise to
follow standard Java naming conventions (i.e. not using underscores in
property names but camel case instead).
this JIRA issue shows why the documentation was updated with this reccomendation, and the part describing the double underscore option were removed.
I suspect your root problem is that Spring/Hibernate is not mapping camel case property names to the snake case names you have for your columns in the database. What you really need is for your property name to be interpreted in the SQL that hiberate generates as S_NAME.
Is that why underscores in your property name are "required"? If so, there are a few solutions:
Option 1: #Column annotation
To get JPA/Hibernate to map to the correct column names you can tell it the names explicitly. Use the annotation #Column(name="...") to tell it what column names to use in SQL. Then the field names are not constrained by the column names.
#Entity
public class Student {
#Id
#Column(name="s_id")
private String sId;
#Column(name="s_name")
private String sName;
//...getters and setters...
}
Option 2: Improved Naming Strategy
Or if your application has a large number of entities, rather than adding #Column to every property, change the default naming strategy in your configuration file to the hibernate improved naming strategy.
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
This naming strategy will convert camelCase to SNAKE_CASE. Then your class could look as simple as this:
#Entity
public class Student {
#Id
private String sId;
private String sName;
//...getters and setters...
}
Using either of those options, when it creates the SQL it will resolve the column names to:
S_ID
S_NAME
Note: If you are using, or can use Spring Boot, the auto-configuration default will use SpringNamingStrategy, which is a slightly modified version of the hibernate improved strategy. You won't have to do anything to get this improved naming strategy.
The finish line:
Using camel case in your property names you can write your repository method name using camel case, and you can stop trying to wrangle the double underscore:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findBySName(String name);
}
Writing double underscore i.e. writing findByS__Name() for property name s_name just does not work. I have tried and tested it. Go by the above answer and change the name of existing instance variables in your entity class. Just dont change getters and setters as they might be used in the existing code.
If you cant change the entities which was my case then better use jqpl query or native sql query on top of repository method
#Query("select s from Student s where s.s_name=?")
List<Student> findBySName();

how can we do to get different types(like the model for view does not need the all fields) in EntityFramework

In NHibernate, we can use setResultTransformer to get different types.
query.setResultTransformer(new AliasToBeanResultTransformer(ViewAd.class));
However, what can we do to get different types(like the model for view does not need the all fields of a table) in EntityFramework?
Thanks in advance.
Try AutoMapper. It allows you to define and use mappings:
Define in Global.asax.cs:
Mapper.CreateMap<Order, OrderDto>();
Use the map in your code:
OrderDto dto = Mapper.Map<OrderDto>(order);

What is the "Func<object> modelAccessor" parameter for in MVC's DataAnnotationsModelMetadataProvider?

It's one of the parameters supplied to the CreateMetadata method (which you override if extending metadata support).
ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor, <<--THIS ONE
Type modelType,
string propertyName)
I had assumed that it allowed you to access the model object itself (e.g. for setting metadata based on model values), however when I try to use it to cast to my model object I just get null.
Entity ent = (Entity)modelAccessor(); // = Null
If I've missunderstood, can anyone explain what it's purpose is? Or alternatively, how to properly use it?
Thanks
We originally had that as "object model", rather than "Func modelAccessor". We had to change it late in MVC 2's ship cycle.
The purpose is to delay retrieving the actual value of the model until such point as you know you're going to need it (that is, until you call ModelMetadata.Model).
The problem it solves is actually a rather esoteric one related to model binding against a LINQ to SQL class that has a foreign key reference in it. The problem is, if you've retrieved the child object which is represented by a foreign key relationship (which usually means a delay load of that object), then you're no longer allowed to choose a new child object by setting the foreign key ID property. It's very common to model bind the foreign key ID (and not the whole foreign key entity) when model binding, but if we'd retrieved the foreign key entity object (for the purposes of populating the ModelMetadata class) then that binding would no longer be legal, and actually throw an exception. Since ModelMetadata is used for both directions of models -- inbound, via model binding, and outbound, via HTML generation -- we needed to introduce the layer of indirection to protect your ability to use it in both scenarios without disrupting LINQ to SQL's rules.
The modelAccessor parameter does not point to an instance of the object, but rather it is a function that will access some attribute of your object. The Func "encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter." For example, if we have following class:
public class Bar(){
[DisplayName("I am Foo.")]
public string Foo{get;}
}
When the CreateMetaData is called, it will be to create meta data for the Foo property and the modelAccessor will be a function that returns the value of Foo.
I did a little digging and found a way to get to the instance of the object, but it requires using reflection. You can do the following to get the Bar class in my example:
if (modelAccessor != null)
{
//Use reflection to get the private field that holds the Bar object.
FieldInfo container = modelAccessor.Target.GetType().GetField("container");
//Invoke field on the modelAccessor target to get the instance of the Bar object.
Bar myObject = (Bar)container.GetValue(modelAccessor.Target);
}
I've only run this against a simple test case, so your mileage may vary, but hopefully this will help clarify what is going on.

JPA validation problem: Entity 'X' has no Id or EmbeddedId

Which, I couldn't quite figure out why Eclipse Galileo's JPA validator would say so, as my class 'X' clearly had an #Id annotation on the primary key "uniqueId". The error would disappear if I commented out the #Basic annotation line, but that didn't quite make sense. Anyway, attaching snippet below from memory:
#Entity
class X {
...
#Id
#Basic(optional=false)
#Column(name="someUniqueId", unique=false)
String uniqueId;
...
}
Is this a bug, or is there a JPA standard which I'm not aware of on the use of annotations?
You have here a similar case which may suggest a case or type issue.
But as mentioned here, I would rather bet on bug 217192 (which can be comared with the "non-bug" 208249)
You can also specify which version of eclipse and Dali JPA Tool you are using.
#EmbeddedId
String uniqueId;
You annotated the "uniqueId" with "unique=false".
This could be the root because IDs have to be unique.
You do not need a #Basic annotation as #Id already restricts the attribute's type (as defined by the spec) and the only information #Basic can add are settings for fetch and optional both of which make no sense for a primary key (i.e. a primary key must have fetch=EAGER and optional=false).