JPA static metamodel for multiple persistence units - jpa

JPA: for the generated static metamodel, for example,
#Entity
public class Foo {
private Long id;
}
#StaticMetamodel(...)
public class Foo_ {
public static volatile SingleAttribute<Foo, Long> id;
}
If the entity class Foo is in multiple persistence units(each persistence unit has a Metamodel), each Metamodel has a different ManagedType instance for the Foo class. which metamodel does the static attributes (e.g. id in the example) belong? Each attribute has method getDeclaringType() which returns ManagedType.

Related

Using #MappedSuperclass in spring repository #Query

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;
}

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);
}

How to declare a base repository for a MappedSuperclass base type with spring data?

We're having a hierarchy of entity classes where all inherit from a BaseEntity #MappedSuperclass. Is there a way to have a spring-data "base repository" that allows you to query for any BaseEntity without having to know it's type and use a specific repository?
#MappedSuperclass
public class BaseEntity {
#Id
private Long id;
private String owner;
// setter/getter etc...
}
#Entity
public class FooEntity extends BaseEntity {
private String foo;
}
#Entity
public class BarEntity extends BaseEntity {
private String bar;
}
/**
* How to declare this base repository....
*/
public interface BaseRepository extends JpaRepository<BaseEntity, ActionPK> {
List<BaseEntity> findByOwner(String owner);
}
#Component
public class MyService {
#Autowired
private BaseRepository baseRepository;
public void doSomething() {
// ... so that is can be used like this:
List<BaseEntity> entities = baseRepository.findByOwner("john");
doSomethingWith(entities);
}
}
I think the only way you could achieve this is to create a Service class that will orchestrate all the calls to your Repository classes that have an owner property. That service call would return your list of BaseEntity objects.

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)

Why does eclipselink 2.5.0 does not support Override TableGenerator or SequenceGenerator in subclasses while hiberate does support?

As titled.
Isn't it common to share Id definition in a base entity class? such as following:
#MappedSuperclass
public abstract class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
public Long getId() {return this.id;}
public void setId(Long id) { this.id = id; }
...
}
While in subclass it is suppose to work as following:
#Entity
#Table(name = "sub_entity_table")
#TableGenerator(name = "SUB_ENTITY_SEQUENCE", initialValue = 1, allocationSize = 100)
public class SubEntity extends BaseEntity {
...
}
Since the GeneratedValue.generator is not specified, then the default value should be specified. The default generator name would be:
a. The nearest upward TableGenerator definition from the entity class, just like inheritance.
b. If situation in "a" does not exist, then use the literal value provided by JPA provider, such as SEQ_GEN_TABLE.
I love eclipseLink so much. I really hope to see this feature included in the next eclipselink release. :)