#NaturalId only valid on root entity (or its #MappedSuperclasses), using Natural Id in Joined, Multiple Table Inheritance - hibernate-entitymanager

basically I cant find in google some similar problems by just pasting the root exception "#NaturalId only valid on root entity (or its #MappedSuperclasses)" in the search tab. I'm using a Joined, Multiple Table inheritance strategy to map my concrete/children Entities(Student,Employee) including their Abstract Parent (Person) to the three tables in my database, so far I never had a problem, Until I realize I need to implement a custom query for my Student Entity, using the Student's studentId. I manage to extract the underlying Hibernate-session from the Entity-manager and now I can clearly see and use the methods I need from my beloved HibernateSession, (we all know Hibernate has methods for naturalIds such as (byId, byNaturalId etc..)), and these kinds of methods are really really REALLY useful for querying entities. So I just annotate my studentId data member with #NaturalId until.. I performed some operation (save/create) and then multiple lines of exception are thrown to me. And the root cause is..
org.hibernate.AnnotationException: #NaturalId only valid on root entity (or its #MappedSuperclasses)
I will paste the codes of my entities for added information
The Parent abstract base class
Person class
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="PERSON_TYPE")
#Table(name="PERSON")
public abstract class Person {
#Id
#GeneratedValue
#Column(name="person_ent_id", insertable = false)
private int personId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "age")
private int age;
#Column(name = "postal_id")
private String postalId;
.. getter and setter methods declarations
The Entity sub-class
Student class
#Entity
#Table(name = "STUDENT")
#DiscriminatorValue("S")
#PrimaryKeyJoinColumn(name = "student_ent_id", referencedColumnName = "person_ent_id")
public class Student extends Person {
#Column (name = "student_ent_id", insertable=false, updatable=false)
private int studentEntId;
#NaturalId
#Column(name = "school_id")
private String schoolId;
#Column(name = "school_name")
private String shoolName;
public Student() {
super();
}
...getter and setter methods declarations
Questions:
Is there a anything I can do to make a unique query for different student entities? because Hibernate's naturalId methods are really useful to perform operations with entities such as get or
update
Is there any work-around to accomplish what I want without sacrificing my Design with the Entities and the database table? I want the studentId to act as a naturalId IF it would be possible. Any suggestions/help/comments please. Any thing will be greatly appreciated.

No, unfortunately this is not possible. I think it's because you can make NaturalId queries only on the whole table, so it needs to be on a root Entity. But if you only want to make sure that schoolId is unique for all Students you can use #Column(name = "school_id", unique = true).

Related

UML class diagram dependency or association

I'm not really sure about how to distinguish whether I should define a relationship as dependency or association for certain cases.
For example,
class AttendanceSheet {
Map<String> students;
boolean[] attend;
public void addStudent(Student s)
{
students.add(s.getName(),s.getStudentNumber());
}
public void checkAttendance(String name) { //... }
}
class Student {
private String name;
private int staffNumber;
//more information such as address, age, etc..
Student(String n, int sn)
{
name = n;
studentNumber = sn;
}
public String getName()
{
return name.clone();
}
public String getStudentNumber()
{
return studentNumber;
}
}
For this case, would Student and Association have association or dependency?
This is because I'm not sure whether the association must have the actual reference of the object or it suffice to just have certain information that can reach the object (since student id and number is far more enough to know find out which student object it is directing to).
In your case the <<uses>> is sufficient, because you don't have actual properties of type Student in AttendanceSheet.
As a side note: not using object references and instead just having the studentNumber is - to say the least - an odd design. But I don't know the context.
On the business level those objects are related, but there is no single preferred method of diagramming this relationship.
Please see Section 9.5.4 of UML specification for more details on the topic, especially Figure 9.12
To be specific those two notations are semantically equivalent (I'm ignoring irrelevant details):
In the first one to keep a traceability you can use an explicit Dependency pretty much the way you did.
One can also consider students as a Shared Aggregation, however it might be also considered an overkill. Not necessary, just showing a possibility for an answer completeness.
You may also consider Qulified associations to indicate a reference to the Student is based on their specific properties. This is pretty much closest to your need. Sorry, I don't know how to achieve such notation in my tool, but you can find more details in Figure 11.37 in Section 11.5 of the aforementioned specification.

Spring data Cassandra polymorphism, override column definition

I'm creating a heirarchy of classes for the purposes of denormalizing a table. Tables are quite wide so to manage hassle and errors, I would like to declare all fields in the parent and then alter the definition of specific fields in the child. This way I can have a normal column in the parent be redefined as part of a primary key in the child.
E.g.:
Basic super-class
public class A {
#Column
protected int age;
}
Class extending A
#Table
public class B extends A {
#PrimaryKey
protected K key;
...
}
Primary key for A, with a new definition of the age column.
#PrimaryKeyClass
public class K {
#PrimaryKeyColumn
private int age;
#PrimaryKeyColumn
private int ignore;
}
That doesn't seem to work. I get a Multiple definition of identifier exception.
So far I can only declare fields that won't change in the parent and then declare all possibly-changing fields in each child. I don't like this because I have to know upfront every field that might become part of future primary keys.
Putting the annotations on the (parent) getters and overriding those doesn't seem to have done anything.
Any way to solve this aside from keeping only never-changing columns in the parent?
Putting the annotations on the (parent) getters and overriding those doesn't seem to have done anything.
Annotating the child getters with #Transient did!
So: annotate the parent getters rather than the fields, make child getters #Transient, move column definition into the key, done.
From here:
http://docs.datastax.com/en/developer/java-driver/3.1/manual/object_mapper/creating/
One powerful advantage of annotating getter methods is that annotations are inherited from overridden methods in superclasses and superinterfaces; in other words, if a getter method is overridden in a subclass, annotations in both method declarations will get merged together. If duplicated annotations are found during this merge process, the overriding method’s annotations will take precedence over the overridden’s.

Ways to return a list of tuple rows through JPA while using PrimeFaces LazyDataModel<T>

There may be situations where we need to return a list of tuple rows from the associated data model i.e not a fully qualified entity but a part of it, specifically a list of selected columns from the associated data-source (may be a database).
I know of some of ways to return a list of tuple rows from the database using JPA like the following
There is no need to look closely into the code from the JPA criteria API, if you were to dislike criteria queries. The question is not directly related to JPA criteria. I prefer JPA criteria to JPQL for no precise reason - just because I like criteria queries very much.
Using a list of object arrays - List<Object[]> :
public List<Object[]> object(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]>criteriaQuery=criteriaBuilder.createQuery(Object[].class);
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.array(selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Using a list of tuples - List<Tuple> :
public List<Tuple> tuple(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple>criteriaQuery=criteriaBuilder.createTupleQuery();
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.tuple(selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Using a list of rows mapped a class of objects - List<MappedClass> :
public List<ProductUtils> constructor(int first, int pageSize) {
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<ProductUtils>criteriaQuery=criteriaBuilder.createQuery(ProductUtils.class);
Root<Product> root = criteriaQuery.from(entityManager.getMetamodel().entity(Product.class));
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(root.get(Product_.prodCode));
selections.add(root.get(Product_.prodDesc));
selections.add(root.get(Product_.marketPrice));
selections.add(root.get(Product_.salePrice));
criteriaQuery.select(criteriaBuilder.construct(ProductUtils.class, selections.toArray(new Selection[0])));
//Or criteriaQuery.multiselect(selections.toArray(new Selection[0]));
return entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();
}
Again the same thing can be rewritten using JPQL.
The first two of them are ugly and require accessing properties using indices in EL on XHTML pages. Maintaining them is difficult, if the order in which the fields appear is changed at a later time (of course, aliases can be used with Tuple). Also, use of Tuple is always avoidable, since it requires an additional dependency in JSF from the javax.persistence package increasing coupling between modules.
Using a constructor query to map the result list to a class may suffice. It can be used along with PrimeFaces LazyDataModel as follows.
#Named
#ViewScoped
public class TestManagedBean extends LazyDataModel<ProductUtils> implements Serializable {
#Inject
private Service service;
private static final long serialVersionUID=1L;
public TestManagedBean() {}
#Override
public List<ProductUtils> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
// Put some logic here like setting total rows for LazyDataModel - setRowCount(10)
return service.constructor(first, pageSize); //Use filters and sort meta whenever necessary.
}
}
But this is also too unmaintainable, if I need to access more or less fields from the database at some later time at a different place that requires creating a new class or adding a new constructor (constructor overloading in the existing class) to the existing class which in turn requires to check carefully the actual and formal parameters of the constructor method to see, if they match in number, order and type precisely that often makes me blind.
I hope, there should be some better ways that allow us to tackle such situations in a precise way.
Parameterized constructor(s) in the existing entity classes, if used instead (without creating a new class like ProductUtils, in this case) may cause problems while implementing web services (JAX-WS) in the application (if needed). Therefore, I never tend to use parameterized constructors of entity classes anywhere.

Map a flat structure to an object with AutoMapper?

The data being returned from a stored procedure has 3 columns of repeating data:
Name | Address | PhoneNumber | UniqueCol1 | UniqueCol2
Ideally I want my model to show that there is repeated data by only storing the values once and have a collection of the unique data.
public class MyViewModel
{
public string Name {get;set;}
public string Address {get;set;}
public string PhoneNumber {get;set;}
public List<MyModel> UniqueData {get;set;}
public class MyModel
{
public string UniqueCol1 {get;set;}
public string UniqueCol2 {get;set;}
}
}
This means I want to map a collection of results to a single object of MyViewModel:
return Mapper.Map<List<StoredProcedureObject>, MyViewModel>(result);
This is where I get my error as I assume I have some configuration that I need to do:
Mapping types:
List`1 -> MyViewModel
Any ideas on the missing step to get this to work?
Automapper is only able to flatten your structure into something simpler. But it's not possible to map a simple class to something more specific.
I would suggest to take only the first entry in your table to fill your base fields like Name, Address, PhoneNumber and iterate over your results to fill your UniqueData List.
I don't see an easier way, because with each possible mapping and without using seperate loops you will get your base data multiple times.
If you don't mind to use another tool, maybe you will have a look at ValueInjecter. I heard you can use this tool for two-way-mappings.

SubSonic How to Execute a SQL Statement?

My site is using Subsonic 2.2 on my site.
I have 1 weird situation where I need to run some ad-hoc SQL statements.
public IList<string> GetDistincList(string TableName, string FieldName)
{
string sqlToRun = string.Format("SELECT DISTINCT {0} FROM {1} ORDER BY {0}", FieldName, TableName);
Query query = new Query(TableName);
query.PleaseRunThis(sqlToRun);
query.ExecuteReader();
}
Can anyone help me here? As it appears, I just want to return a generic list of strings.
Thanks!
Subsonic has a great method called ExecuteTypedList() so you can do somethink like this.
List<int> result = DB.Select(Table.Columns.Id)
.Distinct()
.From<Table>()
.OrderBy(Table.Columns.Id)
.ExecuteTypedList<int>();
or even with pocos:
public class UserResult
{
public int Id {get;set;}
public string Name {get;set;}
}
List<UserResult> users = DB.Select(
User.Columns.UserId + " as Id", // the as ... is only needed if your
User.Columns.UserName + " as Name" // column name differs from the
).From<User>() // property name of your class
.ExecuteTypedList<UserResult>();
Unfortunately this method doesn't work for string since it requires
a) a valuetype
b) a class with a parameterless constructor since the method uses reflection to map the columns from the result to the properties of the class
However I wrote an extension method a while ago that works for string:
Use the Subsonic.Select() ExecuteTypedList Method with String
Look at my own answer in the link.
If you add the extensionmethod to your code you can do:
List<String> result = DB.Select(User.Columns.UserName)
.From<User>()
.ExecuteTypedList();
Use the CodingHorror class.
Here's the SubSonic 3 way of doing it: http://www.subsonicproject.com/docs/CodingHorror
The SubSonic 2 way is similar:
Dim ch As SubSonic.CodingHorror
ch.Execute("delete from #tablename", table)

Resources