Using #MappedSuperclass in spring repository #Query - spring-data-jpa

I am trying to define common query for all repositories extended my base repository:
#NoRepositoryBean
public interface DocumentRepository<T extends BaseDocument> extends JpaRepository<T, Long> {
#Query(value = "FROM BaseDocument bd WHERE (bd.createdAt IS NULL OR :to IS NULL OR bd.createdAt < :to) AND (bd.deletedAt IS NULL OR :from IS NULL OR bd.deletedAt > :from)")
Iterable<T> findAllActiveBetween(OffsetDateTime from, OffsetDateTime to);
}
#MappedSuperclass
#Where(clause="deleted_at IS NULL")
abstract public class BaseDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private OffsetDateTime createdAt;
private OffsetDateTime deletedAt;
}
The problematic part is using BaseDocument in #Query.
It is posible to define such method without duplication in all sub-repositories?

When you use #MappedSuperclass the inherited classes do not share a table to select from, so each of them needs a separate query. Inheritance of the repository cannot help you here.
If you use another inheritance strategy, for example a joined multiple table inheritance it would be possible to select from the table of the superclass and then you can use the java objects to navigate. If you need to use properties from the subclass in the query, each subclass would need to implement their own queries of course.
#NoRepositoryBean
public interface DocumentRepository<T extends BaseDocument> extends JpaRepository<T, Long> {
#Query(value = "FROM BaseDocument bd WHERE (bd.createdAt IS NULL OR :to IS NULL OR bd.createdAt < :to) AND (bd.deletedAt IS NULL OR :from IS NULL OR bd.deletedAt > :from)")
Iterable<T> findAllActiveBetween(OffsetDateTime from, OffsetDateTime to);
}
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="BaseDocument_TYPE")
#Table(name="BaseDocument")
abstract public class BaseDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private OffsetDateTime createdAt;
private OffsetDateTime deletedAt;
}
#Entity
#DiscriminatorValue("TextDocument")
#Table(name="TextDocument")
public class TextDocument extends BaseDocument {
private String text;
}
#Entity
#DiscriminatorValue("AudioDocument")
#Table(name="AudioDocument")
public class AudioDocument extends BaseDocument {
private byte [] audio;
}

Related

JPQL query on abstract mother class accessing subclasses properties

I'm facing a problem trying to make a JPA repository on an abstract class.
What I'm willing to do is a method that filters, paginates and returnes 3 differents kind of objects in a single list. Some have shared properties (grouped in AbstractClass).
Here are my different classes :
Mother abstract class
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "te_abstract_data")
#DiscriminatorColumn(name="data_type")
public abstract class AbstractData {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "data_type")
#Enumerated(EnumType.STRING)
private DataType dataType;
}
AbstractClass
#MappedSuperclass
public class AbstractClass extends AbstractData {
#ManyToOne
#JoinColumn(name = "fk_obj_id")
private ObjEntity opbj;
}
ClassA & ClassB classes
#Entity
#DiscriminatorValue("CLASS_A")
#Table(name = "te_class_a")
#PrimaryKeyJoinColumn(name="fk_data_id")
public class ClassAEntity extends AbstractClass {
// some fields...
}
ClassC
#Entity
#DiscriminatorValue("CLASS_C")
#Table(name = "te_class_c")
#PrimaryKeyJoinColumn(name="fk_data_id")
public class ClassCEntity extends AbstractData {
// some fields...
}
And here is my repository :
#Repository
public interface DataDao extends JpaRepository<AbstractData, Integer> {
#Query(value =
"SELECT ad " +
"FROM AbstractData ad " +
"WHERE ad.obj.name = :objName " +
// some other filters on various fields
"ORDER BY ad.id ASC"
)
List<AbstractData> findFiltered(
Pageable pageable,
String objName
);
}
The current query in my repository ignores only returns ClassB object, even if ClassA and C's objects are well initialized. I have no idea about what could be wrong...
Any idea how I could solve this ?

Build method in JPA with composite key

This is my entity with composite key:
#Entity
#Table(name = "course_ratings")
public class CourseRating {
#EmbeddedId
private CourseRatingKey id;
}
Where CourseRatingKey looks like this:
#Embeddable
public class CourseRatingKey implements Serializable {
#Column(name = "user_id")
private int userId;
#Column(name = "course_id")
private int courseId;
public CourseRatingKey() {
}
// getters, setters, equals(), hashCode()
}
And my JPA repository
#Repository
public interface CourseRatingRepository extends JpaRepository<CourseRating, CourseRatingKey> {
}
I am trying to build method that will return list of all CourseRating with given courseId property of CourseRatingKey. Below method doesn't work because JPA doesn't recognize it:
repository.findAllByIdCourseId(int id);
How can I build my method name to achieve my goal?
I have solved my problem by declaring this method in repository. I'm a bit confused as the other methods work without declaring.
#Repository
public interface CourseRatingRepository extends JpaRepository<CourseRating, CourseRatingKey> {
List<CourseRating> findAllByIdCourseId(Integer id);
}

Spring JPA using primary key within #Embeddable class

In my application i have a scenario to fetch data from entity based on give input code and date.
The combination of code and date will be unique and will return a single record.
Below is my entity
class JpaEntity
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
private String code;
private Date date;
private title;
//Getters and Setters
}
I have tried below approcah by changing the entity.
class JpaEntity
{
private String title;
//Getters and setters
#EmbededId
private EntityId entityID
#Embedable
public static class EntityId implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
private String code;
private Date date;
//Getters and Setters
}
}
I am using the entity to search based on code and date
public interface PersistentDAO extends JpaRepository<JpaEntity,String> {
{
#Query("SELECT cal FROM JpaCalendar cal" + " WHERE cal.calendarId.currencyCode=:currencyCode "
+ " AND cal.calendarId.date=:date")
Optional<JpaCalendar> findById(String currencyCode, Date date);
JpaEntity findByID(String code,Date date)
}
But the JPA is throwing error saying Component Id is not found.
is it mandatory all the field in #Embedable are primary?
is it possible #Embedable class (composite id) contain the both primary and non-primay keys.
Since i am not supposed to change the structure of the table is there any way to achieve following:
Fetch record based on give code and date.
Insert new record where in id the primary key should be auto incremented
Please suggest.
Use #Embedded & #Embeddable and don't use static class inside class
class JpaEntity
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
#Embedded
private CodeDate codeDate;
private title;
}
#Embeddable
class CodeDate {
private String code;
private Date date;
}
You can use Jpa method naming query and create a CodeDate object call like this
public interface PersistentDAO extends JpaRepository<JpaEntity,String> {
{
JpaEntity findByCodeDate(CodeDate codeDate);
}

#ManyToOne conflicts with JpaRepository

#ManyToOne or #OneToOne will replace the joined column with an entity, but how would I do when I want to use JpaRepository to query by that joined column? There's seems a conflict.
#Entity
public class Type {
private Long id;
}
#Entity
public class Item {
#ManyToOne
#JoinColumn(name = "type_id")
private Type type;
}
public interface ItemRepository extends JpaRepository<Item, Long> {
List<Item> findByTypeId(Long typeId);
}
It throws error "property typeId not found", which makes sense because it's surely not in the class "item", instead an entity "type". But how could I query Item by type_id in this situation? And if I declare property typeId, it will throw error duplicated mapping for column "type_id".
You have to do it with _ like
public interface ItemRepository extends JpaRepository<Item, Long> {
List<Item> findByType_Id(Long typeId);
}

Accessing #MappedSuperclass' properties in Criteria Query using metamodel classes

I'm trying to access a property defined in #MappedSuperclass in a Criteria Query with JPA meta-model (Hibernate 4.2.8):
#MappedSuperclass
public class BaseEntity {
private DateTime createdOn;
}
My Entity:
#Entity
#Table(name = "HISTORY")
public class History extends BaseEntity implements Serializable {
private Long id;
}
How to access createdOn?
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<History> c = cb.createQuery(History.class);
Root<History> h = c.from(History.class);
h.orderBy(cb.asc(a.get(History_.createdOn)));
History_:
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(History.class)
public abstract class History_ extends com.test.BaseEntity_ {
public static volatile SingularAttribute<History, Long> id;
}
Is there a way to access base class' properties?
Of course there is a way. As I see in your code, you already access it: History_.createdOn is a property of the MappedSuperclass. If by "to access" you mean to select, than you simply do:
query.select(History_.createdOn)