#OrderBy Annotation in Hibernate Not Working - java

import org.hibernate.annotations.OrderBy;
import javax.persistence.Column;
import javax.persistence.Entity;
public class A implements Serializable
{
#Id
#Column(name="SNR")
private long ASnr;
#OneToMany(fetch=FetchType.EAGER)
#JoinColumn(name="B")
private Set<B> bset;
public Set<B> getB() {
return this.bset;
}
#OrderBy(clause="bsnr DESC")
public void setB(Set<B> bset) {
this.bset = bset;
}
}
public class B implements Serializable
{
#Id
#Column(name="BSNR")
private long bsnr;
public long getBsnr() {
return this.bsnr;
}
public void setBsnr(long bsnr) {
this.bsnr= bsnr;
}
}
For above code #OrderBy is not working. When i try to make hibernate query then only select query is showing on console and there is no order by clause inside the sql query. Have i left something or written incorrect ?

you have used
import org.hibernate.annotations.OrderBy;
did you try with
import javax.persistence.OrderBy;
#OrderBy("bsnr")
I think you're misunderstanding what the #Orderby annotation actually does. According to the javadoc:
Specifies the ordering of the elements of a collection valued
association or element collection at the point when the association or
collection is retrieved.
The annotation does not dictate insertion order
Try adding on property or getter

I added antlr-2.7.7.jar in the classpath and used javax.persistence.OrderBy in code. Now it's working perfectly.

Related

Problem when using Spring Specification with One-To-Many relationship

I'm having a problem with Specification as stated in the title.
Here is my FishingLocation class:
#Entity
#Table(name = "tbl_fishing_location")
public class FishingLocation {
...
#JsonIgnore
#OneToMany(mappedBy = "id", fetch = FetchType.EAGER)
private List<Lake> lakeList;
...
}
And here is my Lake class:
#Entity
#Table(name = "tbl_lake")
public class Lake {
...
#JsonIgnore
#ManyToOne
#JoinColumn
private FishingLocation fishingLocation;
...
}
They both have a StaticMetamodel as follow:
#StaticMetamodel(FishingLocation.class)
public class FishingLocation_ {
public static volatile ListAttribute<FishingLocation, Lake> lakeList;
public static volatile SingularAttribute<FishingLocation, Long> id;
}
#StaticMetamodel(Lake.class)
public class Lake_ {
public static volatile SingularAttribute<Lake, Long> id;
public static volatile SingularAttribute<Lake, FishingLocation> fishingLocation;
}
I have created a Specification to filter FishingLocation as follow (the fishing method is not relevant):
public static Specification<FishingLocation> fishingMethodIdIn(Set<Long> fishingMethodIds) {
if (fishingMethodIds == null || fishingMethodIds.isEmpty()) {
return null;
}
return root.join(FishingLocation_.lakeList)
.join(Lake_.fishingMethodList)
.get(FishingMethod_.id).in(fishingMethodIds);
};
}
The problem is that when I run the program and send a request to filter, Hibernate showed me this SQL query:
select
fishingloc0_.id as id1_7_,
fishingloc0_.active as active2_7_,
...
from
tbl_fishing_location fishingloc0_
.... (some inner joins)
inner join
tbl_lake lakelist4_
on fishingloc0_.id=lakelist4_.id
....
It is supposed to be on fishingloc0_.id=lakelist4_.fishing_location_id. So where is the problem in my code? Huge thanks to anyone helping me with this problem.
Edit: This is just a small fraction of my code. My filter has multiple criteria and join many tables so I cannot just use premade function in FishingLocationRepository. I want to create dynamic query which should be build depend on what user chooses to filter by.
you don't need to call this all using custom queries the Hibernate will take care of everything with OneTO Many and ManyTOOne mappings.
You can get the required data by simply calling the getter methods of its class.
for example, in the case of Fishing Location, you can get all the lakes related to that location by calling new FishingLocation().getLakeList().
same for the other case. https://www.javatpoint.com/hibernate-many-to-one-example-using-annotation

Logical delete at a common place in hibernate

I am using Spring and Hibernate for my application.
I am only allowing logical delete in my application where I need to set the field isActive=false. Instead of repeating the same field in all the entities, I created a Base Class with the property and getter-setter for 'isActive'.
So, during delete, I invoke the update() method and set the isActive to false.
I am not able to get this working. If any one has any idea, please let me know.
Base Entity
public abstract class BaseEntity<TId extends Serializable> implements IEntity<TId> {
#Basic
#Column(name = "IsActive")
protected boolean isActive;
public Boolean getIsActive() {
return isActive;
}
public void setIsActive(Boolean isActive) {
isActive= isActive;
}
}
Child Entity
#Entity(name="Role")
#Table(schema = "dbo")
public class MyEntity extends BaseEntity {
//remaining entities
}
Hibernate Util Class
public void remove(TEntity entity) {
//Note: Enterprise data should be never removed.
entity.setIsActive(false);
sessionFactory.getCurrentSession().update(entity);
}
Try to replace the code in setIsActive method with:
public void setIsActive(Boolean isActive) {
this.isActive = isActive;
}
in your code the use of variable name without this could be ambiguos...
I think you should also add #MappedSuperclass annotation to your abstract class to achieve field inheritance.
The issue with the proposed solution (which you allude to in your comment to that answer) is that does not handle cascading delete.
An alternative (Hibernate specific, non-JPA) solution might be to use Hibernate's #SQLDelete annotation:
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/querysql.html#querysql-cud
I seem to recall however that this Annotation cannot be defined on the Superclass and must be defined on each Entity class.
The problem with Logical delete in general however is that you then have to remember to filter every single query and every single collection mapping to exclude these records.
In my opinion an even better solution is to forget about logical delete altogether. Use Hibernate Envers as an auditing mechanism. You can then recover any deleted records as required.
http://envers.jboss.org/
You can use the SQLDelete annotation...
#org.hibernate.annotations.SQLDelete;
//Package name...
//Imports...
#Entity
#Table(name = "CUSTOMER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
#SQLDelete(sql="UPDATE customer SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
#Where(clause="deleted <> '1'")
public class Customer implements java.io.Serializable {
private long id;
...
private char deleted;
Source: http://featurenotbug.com/2009/07/soft-deletes-using-hibernate-annotations/

What is #StaticMetamodel and SingularAttribute<Obj,Obj>?

I am trying to figure out this code for about two hours now, for example in below class what are these fields representing?
import java.util.Date;
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
import java.util.UUID;
#StaticMetamodel(Address.class)
public class Address_ extends {
public static volatile SingularAttribute<Address, Long> id;
public static volatile SingularAttribute<Address, UUID> personId;
public static volatile SingularAttribute<Address, Person> person;
}
The Address.class is a java class which has the following definition:
#Entity
#Table(name = "address", schema = "public")
public class Address{
private Long id;
private Person person;
private UUID personId;
//....
}
Can you, please, explain what are the #StaticMetamodel and #SingularAttribute annotations used for? It might be simple but I can't understand.
As per documentation:
A static metamodel is a series of classes that "mirror" the entities
and embeddables in the domain model and provide static access to the
metadata about the mirrored class's attributes.
The static metamodel has the following properties:
For each managed class X in package p, a metamodel class X_ in package p is created.
For every persistent non-collection-valued attribute y declared by class X, where the type of y is Y, the metamodel class must contain a declaration as follows:
SingularAttribute example:
public static volatile SingularAttribute<X, Y> y;
The static metamodel is useful for creating type-safe queries with the JPA's Criteria API.
For example, let's have the following two entities, Order and Item:
#Entity
public class Order {
#Id
#GeneratedValue
Integer id;
#ManyToOne
Customer customer;
#OneToMany
Set<Item> items;
BigDecimal totalCost;
// accessors
}
and the Item entity:
#Entity
public class Item {
#Id
#GeneratedValue
Integer id;
int quantity;
#ManyToOne
Order order;
// accessors
}
Here's a typesafe criteria query, build with the Criteria API:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where(cb.equal(itemNode.get(Item_.id), 5)).distinct(true);
Note the usage of Item_.id and Order_.item. Those access statically the static meta-model properties (which mirror the entity properties) and this way it's ensured that the query is build properly.
I've been thinking about this a lot lately as I've been trying to learn and understand JPA. I believe I have an answer to your question: Why do we need MetaModels, and why can't we just use the Entity Model?
Take a look at this entity:
#Entity
public class Item {
#Id
#GeneratedValue
Integer id;
int quantity;
#ManyToOne
Order order;
// accessors
}
Note that none of the properties on the Entity have the keyword static. That means that in order to use them, we need to create a new Object.
When we are building queries with CriteriaBuilder, we don't need to create an object... we just want to use the properties on the Entity to generate our query. This is the reason we have MetaModels! They create static properties that we can access without having to create an object. So we can can do things like Konstantin mentioned:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where(cb.equal(itemNode.get(Item_.id), 5)).distinct(true);
Here, we aren't making an "Item" object... we just need to know the properties of it. The static properties on the MetaModel enable us to do so!

OpenJPA + Derby ManyToOne issue after update OpenJPA from 1.2 to 2.2

I just updated OpenJPA from version 1.2 to 2.2 and many of my JUnits failed. Most of them because ManyToOne relation changed behavior. Lets say we have two entities
package org.my;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
#Entity
public class Many {
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private One one;
public One getOne() {
return one;
}
public void setOne(One one) {
this.one = one;
}
}
and
package org.my;
import java.util.List;
#Entity
public class One {
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "one")
private List<Many> many;
public List<Many> getMany() {
return many;
}
public void setMany(List<Many> many) {
this.many = many;
}
}
When I Create One object and set to it List of Many, than persist and commit I got an exception like this
org.apache.openjpa.persistence.InvalidStateException: The field "one" of instance "org.my.Many#4d9cfefb" contained a null value; the metadata for this field specifies that nulls are illegal.
I thought that OpenJPA cat find One object and put it into Many.one field, am I wrong? If not how can I achieve this?
Every Many object in the List of One object should be setOne first before you save it

Is it possible to set Hibernate's "default" variable name mapping?

I'm looking for a way to set the "default" mapping that Hibernate applies to a variable name in a Java object to query it against the database. At the moment we are using the inline javax.persistence markup to manually set column names, but since we have a rigid naming policy for our database it would be nice to be able to just skip on the manual naming and let Hibernate do the mapping. However, at the moment this doesnt work nice at all with anything save for local, non-primary key fields.
At the moment, Hibernate seems to be set to map non-foreign keys to just their name (see "foo" in the below example class), and foreign-keys to "variableName_ReferencedTable_Id" (see "bar" in the below example class). We would like non-foreign keys to stay as they are, except for the variable marked #id, which we would like to be mapped to "TableName_Id", and we would like foreign keys to be mapped to "variableName_Id". Is this even possible, or do we just have to put up with manual mapping?
package testPackage.test
import javax.persistence.CascadeType;
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;
#Entity
public class Table1 {
private int id;
private int localVariable;
private int foreignKeyVariable;
// Constructor here somewhere
// Without a #Column( name="Table1_Id" ), this comes out as "id".
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// This works fine, being a local field.
public int getLocalVariable() {
return localVariable;
}
public void setLocalVariable(int LocalVariable) {
this.localVariable = localVariable;
}
// Withou a #JoinColumn( name="foreignKeyVariable_Id" ) , this comes out as "foreignKeyVariable_Table2_Id".
#ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
#JoinColumn() // Not sure if this would even be necessary at all. Happy to leave it out if possible.
public int getForeignKeyVariable() {
return foreignKeyVariable;
}
public void setForeignKeyVariable(int foreignKeyVariable) {
this.foreignKeyVariable = foreignKeyVariable;
}
}
(copied from comment)
Hibernate does have the concept of NamingStrategy, but it's not sensitive to whether than object is a PK or a normal column, so that's not going to be of any use.

Categories