I am using JPA query in spring , My subclass extends Baseclass whic contains an Id only and My subclass has all the variavles that is used by the JPA query given below:
Base Class:
#MappedSuperclass
#Table(name = "partcost")
#NoArgsConstructor
#AllArgsConstructor
#Data
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Pg6p0012_01PartCostBaseQueryModel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
String part_no;
}
Subclass :
#Entity
#Table(name = "partcost")
#NoArgsConstructor
#AllArgsConstructor
#Data
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Pg6p0012_01PartCost1QueryModel extends Pg6p0012_01PartCostBaseQueryModel implements Serializable {
private static final long serialVersionUID = 1L;
private String stock_take_cost ;
private String cost_type ;
}
when I am hiting below JPA Query :
#Repository
#Transactional
public interface Pg6p0012_01PartcostRepository extends JpaRepository<Pg6p0012_01PartCostBaseQueryModel, String> {
#Query(value = "SELECT stock_take_cost,cost_type FROM partcost where part_no = :p_part_no", nativeQuery = true)
public List<Pg6p0012_01PartCost1QueryModel>getPartcost1Result(#Param("p_part_no") String p_part_no);
}
its throwing Error: No such column name
which is clear because query is returning only one column but Model has two columns .
How to tackle this ? please suggest.
You make part_no transient . It means that it is not persisted in the database.Therefore you are getting no such column name error. Remove #Transient from the base class which is above the part_no.
And also annotate your base class with
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
Hibernate supports the three basic inheritance mapping strategies:
table per class hierarchy
table per subclass
table per concrete class
Related
I'm trying to access an attribute in one of my entity classes: "products" that is a list:
#Entity
#Table(name = "TRANSACTION")
#Getter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Transaction extends BaseTransaction {
...
#OneToMany(mappedBy="transaction)
private List<Product> products;
...
}
#Entity
#Table(name = "PRODUCT")
#Getter
#AllArgsConstructor
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Product {
....
#ManyToOne
#PrimaryKeyJoinColumn
#Getter
#NonNull
private Transaction transaction;
....
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "name", column = #Column(name = "seller_name")),
#AttributeOverride(name = "country", column = #Column(name = "seller_country")) })
private NameAndCountry seller;
...
}
#Embeddable
#AllArgsConstructor
#Getter #Setter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NameAndCountry {
private String name;
private String country;
}
Given a string: "myName", and by using JPA criteria builder, I'm trying to retrieve the name of the seller of the transaction, and this is what have when I'm trying to build the predicate:
Join<Object, Object> transactionProductJoin = root.join("products");
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");
However I'm facing an error which says:
Unable to locate Attribute with the the given name [products] on this ManagedType [work.my.domain.models.BaseTransaction]
Why is JPA criteria builder trying to retrieve the "products" attribute from the parent class of Transaction? What should be the correct way to construct the predicate?
Following is the example where we map Parent and Child entity classes using JPA Annotations.
#Entity
#Table(name = "Parent")
#Inheritance(strategy = InheritanceType.JOINED)
public class Parent {
// Getter and Setter methods
}
#Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.
#InheritanceType – Defines inheritance strategy options.
Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy
Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses
Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.
#Entity
#Table(name="Child")
public class Child extends Parent {
//Getter and Setter methods,
}
#Inheritance(strategy = InheritanceType.JOINED)
Should be added to the parent entity. (Depending on the InheritanceType required for your scenario.)
Check these links for reference:
Chapter 10. Inheritance mapping
5.1.6. Inheritance strategy
The issue is solved, the problem was in the construction of the predicate:
Wrong:
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");
Correct:
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("seller").get("name"), "myName");
I have two tables A and B:
#Entity
public class A {
}
#Entity
public class B {
private final A a;
private String someBSpecificField;
}
Entity A is already Coded nicely and mapped to an existing table. My job is to create B and for some reason I prefer composition over inheritance between A and B. At the same time I want to have single table for A and B to avoid joins when reading. Can I do like this:
#Entity
#Table(name = "a")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "a_type_enum", discriminatorType =
DiscriminatorType.INTEGER)
#DiscriminatorValue("100")
public class A {
}
#Entity
#Table(name = "a")
#DiscriminatorValue("500")
public class B {
private final A a;
private String someBSpecificField;
}
If the type is a complex object then you need to annotate that type with #Embeddable and use it in your #Entity class.
if you want to override the attribute names for your #Embeddable class so they have different column names, you can do so with the #AttributeOverrides annotation.
I have a few tables named MEMBER, PROVIDER, EMPLOYER etc and they have few common columns like ID, ADDRESS etc. I'm using hibernate to fetch data from these tables using Spring Data JPA. Since I have many similar tables, I created a super entity class and wrote a common method to fetch the data. Here is my super class.
#Entity
#Getter
#Setter
#NoArgsConstructor
#ToString
public abstract class Recipient implements Serializable {
#Id
#Column(name = "RECIPIENT_ID", unique = true, nullable = false)
private Long id;
}
Here is a sample entity which extends this super class.
#Entity
#Getter
#Setter
#NoArgsConstructor
#ToString
#Table(name = "MEMBER")
public class Member extends Recipient {
#Column(name = "Member_NAME")
private String membername;
}
Here is the Service
public class RecipientServiceImpl extends AbstractService<Recipient>
implements RecipientService {
#Override
public Recipient findByIdAndType(long id, String type) {
Recipient recipient = null;
switch (RecipientType.get(type)) {
case MEMBER:
recipient = recipientRepository.findMemberById(id);
case PROVIDER:
recipient = recipientRepository.findProviderById(id);
case EMPLOYER:
recipient = recipientRepository.findEmployerById(id);
}
}
And here is the repository
public interface RecipientRepository
extends JpaRepository<Recipient, Long>, JpaSpecificationExecutor<Recipient> {
public Member findMemberById(long id);
public Provider findProviderById(long id);
public Employer findEmployerById(long id);
}
Obviously it didn't work since there weren't any tables mapped in the Recipient abstract entity. Is there a way to implement what I was hoping for as a generic fetching method instead of having to create repositories for each entities ?
I have an inheritance relationship of entities with joined type.
#Entity
#Table(name = "MSM_SUBSCRIPTION")
#DiscriminatorColumn(name = "SUBSCRIPTIONTYPE", discriminatorType = DiscriminatorType.STRING, length = 100)
class subscription {
}
#DiscriminatorValue("com.xxx.XXXSubscription")
#Table(name = "XXX")
public class XXXSubscription extends Subscription implements Serializable {
}
When I'm trying to use a named query such as
SELECT s.class AS subscriptiontype,
FROM
Subscription s
It is resulting in the following query
select
case
when s1_.subscriptionId is not null then com.xxx.XXXSubscription
when s.subscriptionId is not null then 'Subscription'
end AS subscriptiontype,
from
MSM_SUBSCRIPTION s
left outer join
XXXSubscription s1_
on s.subscriptionId=s6_.subscriptionId
Which throws an error as below.
-ORA-00904: "COM"."xxx"."MMSSUBSCRIPTION": invalid identifier
As I noticed, there are no tags around the case statement in generated query, on manually firing this query with tags around the DiscriminatorValue 'com.xxx.XXXSubscription', the query is running fine.
Can someone please help ??
try this
you can define super class with #inheritance annotation
#Entity
#Table(name = "MSM_SUBSCRIPTION")
**#Inheritance(strategy = InheritanceType.SINGLE_TABLE)**
#DiscriminatorColumn(name = "SUBSCRIPTIONTYPE", discriminatorType = DiscriminatorType.STRING, length = 100)
class subscription {
}
#DiscriminatorValue("com.xxx.XXXSubscription")
#Table(name = "XXX")
public class XXXSubscription extends Subscription implements Serializable {
}
Im using Hibernate with JPA 2.1 and I want to define an entity with two sub entities. My problem is that I want to define an UniqueConstraint with two columns: One MemberField and the DiscriminatorColumn.
EDIT: Because the answer of Nicholas solved my specific problem I changed the type of the parent class from abstract to non-abstract.
My code looks like this:
Parent
#Entity
#Inheritance
#DiscriminatorColumn(name = "TYPE")
#Table(name = "EXAMPLE", uniqueConstraints = #UniqueConstraint(columnNames = { "TYPE", "NAME" }) )
public class ExampleParent extends AbstractEntity
{
private static final long serialVersionUID = 68642569598915089L;
#Column(name = "NAME", nullable = false, length = 30)
#NotNull
private String name;
...
}
Child 1
#Entity
#DiscriminatorValue("TYPE1")
public class Example1 extends ExampleParent
{
private static final long serialVersionUID = -7343475904198640674L;
...
}
Child 2
#Entity
#DiscriminatorValue("TYPE2")
public class Example2 extends ExampleParent
{
private static final long serialVersionUID = 9077103283650704993L;
...
}
Now I don't want a UniqueConstraint on the name of the ExampleParent, because I want to be able to persist two objects of Example1 and Example2 with the same name. The following code should explain it:
#Autowired
Example1Repository example1Repo;
#Autowired
Example2Repository example2Repo;
Example1 example1 = new Example1();
example1.setName("example");
example1Repo.save(example1);
Example2 example2 = new Example2();
example2.setName("example");
example2Repo.save(example2);
So my goal is to set a UniqueConstraint of two columns but I actually want to use the DiscriminatorColumn and a field of my ExampleParent. The combination of the DiscriminatorColumn and the name should be unique.
My code doesn't work, so what are my options?
If you are using an abstract base class I would expect that you would be using a #MappedSuperclass annotation instead of #Inheritance.
#MappedSuperclass is better for polymorphism, which is what you have. I don't think that #Inheritence supports polymorphism.