JPA : Entity extend with entity - jpa

How can I extend an entity with another entity but both of them referring to the same table ? Is it possible ? The structure is something like this :
#Entity
#Table(name = "users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable{
private int id;
private String name;
}
#Entity
#Table(name = "users")
#NamedQuery(name="SubUser.findAll", query="SELECT su FROM SubUser su")
public class SubUser extends User {
#Override
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return super.getId();
}
//- Other fields and getter setter
}
I tried this way Extend JPA entity to add attributes and logic
but I got this exception
org.hibernate.mapping.SingleTableSubclass cannot be cast to org.hibernate.mapping.RootClass
Update 1
I already put the #Id for the SubUser because the #Entity shows this exception
The entity has no primary key attribute defined

Add the #Inheritance annotation to the super class
Implement Serializable
Add a getter for id (you don't need a setter necessarily)
id should be Integer, not int, so that you can represent unassigned ids with null.
Code:
#Entity
#Table(name = "users")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
public class SubUser extends User {
}

Any basic JPA docs would describe inheritance, discriminators and use of #Id.
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="DISCRIM", discriminatorType=DiscriminatorType.STRING)
#DiscriminatorValue("User")
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
}
#Entity
#DiscriminatorValue("SubUser")
#NamedQuery(name="SubUser.findAll", query="SELECT su FROM SubUser su")
public class SubUser extends User {
}

Related

JPA composite Foreign Key part of composite Primary Key unable to find ID

We have tables,
'Lin_Code_Groups' with fields,
Project_ID (PK),
CG_ID(PK),
CG_Name
Corresponding entity class,
public class Lin_Code_Groups implements Serializable {
#EmbeddedId
private LinCodeGroupPK pk;
private String CG_name;
#Embeddable
public static class LinCodeGroupPK implements Serializable {
private Integer Project_ID;
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer CG_ID;
}
#OneToMany(mappedBy = "lin_Code_Groups")
private List<Lin_CG_Params> lin_CG_Params;
}
table Lin_CG_Params with fields,
Project_ID (PK)..FK to Lin_Code_Groups,
CG_ID(PK)...FK to Lin_Code_Groups,
Param_name(PK),
Param_value
Corresponding entity class,
public class Lin_CG_Params implements Serializable {
#EmbeddedId
private LinCodeGroupParamPK pk;
private String Param_value;
#Embeddable
public static class LinCodeGroupParamPK implements Serializable {
private String Param_name;
private LinCodeGroupPK linCodeGroupPK;
}
#MapsId("linCodeGroupPK")
#ManyToOne
#JoinColumns( {
#JoinColumn(name = "Project_ID",referencedColumnName= "Project_ID"),
#JoinColumn(name = "CG_ID",referencedColumnName= "CG_ID")
})
private Lin_Code_Groups lin_Code_Groups;
}
in controller class, i am using JPA's .Save method to save the data in to the tables.
#PostMapping(value = {"/hello"}, consumes = "application/json", produces = "application/json")
public ResponseEntity<Object> saveNewCodeGroupsDetails(#RequestBody Lin_Code_Groups objLin_Code_Groups ) {
respository.save(objLin_Code_Groups);
}
but getting an error 'Unable to find Lin_CG_Params with id Lin_CG_Params.LinCodeGroupParamPK'
Can anyone is please help ?

Query for joins in Spring JPA

I have the below entities
#Entity
#Getter
#Setter
public class Aggregate {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(mappedBy = "aggregate")
private Set<Single> singleSet;
}
#Entity
#Getter
#Setter
public class Single {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String id;
private Integer number;
#ManyToOne
#JoinColumn(name = "agg_id")
private Aggregate aggregate;
}
I also have the below repository
public interface AggregateRepo extends CrudRepository<Aggregate, Long> {
}
I want to return all associated Single records where number in object Single is equal to some random number
I am assuming that the query will be something like this
public interface AggregateRepo extends CrudRepository<Aggregate, Long> {
public List<Single> findBySingleSet_Number(Integer number);
}
However when I try to use Intellij to complete my named query it always populates like this
public interface AggregateRepo extends CrudRepository<Aggregate, Long> {
public List<Single> findBySingleSet_Empty_Number(Integer number);
}
I am wondering what the Empty stands for ?
Also should I create another Single repository since the query is related to returning Single records.

How to handle compound key with relationship in JPA2 and Spring Data JPA?

I have a problem to handle mapping object relationship for mysql tables.
I have 2 tables shown below:
Device
-----------
deviceId PK
deviceName
ApkInfo
--------
id PK
packageName
appName
deviceId FK
And then here are my classes:
#Entity
#Table(name="Device")
public class Device implements Serializable {
#Column
#Id
private String deviceId;
#Column
private String deviceName;
//getters and setters
}
#Entity
#Table(name="ApkInfos")
public class ApkInfo implements Serializable {
#Column
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column
#Id
private String packageName;
#Column
private String appName;
#Column
#Temporal(TemporalType.TIMSTAMP)
private Date installDate;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
This works for me, but I want to use compound key, deviceId and packageName, in ApkInfos table.
#Entity
#Table(name="ApkInfos")
public class ApkInfo implements Serializable {
#Colum(instable=false, updatable=false)
#Id
private String deviceId;
#Column
private String packageName;
#Column
private String appName;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
But when I tried to save an entity using Spring Data JPA repository, I got an error:
org.springframework.dao.InvalidAccessApiUsageException: Class must not
be null, nested exception is java.lang.IllegalArgumentException: Class
must not be null
ApkInfo apkInfo = new ApkInfo();
apkInfo.setDeviceId("1234");
apkInfo.setPackageName("aaa");
apkInfo.setAppName("myapp");
apkInfo.setInstallDate(new Date());
apkInfo.setDevice(new Device("1234"));
repository.save(apkInfo);
And device has the deviceID '1234' already exists in the Device table.
I created a separate primary key class added #IdClass in the ApkInfo class. It works fine now, thanks. I am going to have a look at EmbeddedId more later.
I added #IdClass at the entity class and #Id for the packageName property. Also I made insert, update false for the One-to-many column.
#Entity
#Table(name="ApkInfos")
#IdClass(ApkInfo.class)
public class ApkInfo implements Serializable {
#Column #Id private String deviceId;
#Column #Id private String packageName;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId", insetable=false, updatable=false)
private Device device;
//getters and setters missing
}
Primary key class has only setters and overrides equals and hasCode methods.
public class ApkInfo implements Serializable {
private String deviceId;
private String packageName;
public ApkInfo(){}
public ApkInfo (String deviceId, String packageName){
this.deviceId = deviceId;
this.packageName = packageName;
}
public String getDeviceId(){
return this.deviceId;
}
public String getPackageName(){
return this.packageName;
}
#Override
public boolean equals(Object obj){
return (obj!=null &&
obj instanceof ApkInfoPk &&
deviceId.equals(((ApkInfoPk)obj).getDeviceId()) &&
packageNames.equals(((ApkInfoPk)obj).getPackageName()) );
}
#Override
public int hashCode(){
super.hashCode();
}
}

Exception thrown with OneToMany annotation

In my Play 2.0 application using the EBean ORM I have the following class:
#Entity
public class User extends Model {
#Id
public Long id;
#Constraints.Required
public String someString;
#OneToMany(mappedBy="user", cascade=CascadeType.REMOVE)
#OrderBy("index")
public List<UserImage> userImages = new ArrayList<UserImage>();
}
Unless I comment out the #OneToMany line completely, the application throws a RunTimeException stating
Error reading annotations for models.User
The UserImage class I refer to here looks like this:
public class UserImage extends Model {
#Id
public long id;
#Constraints.Min(0)
public int index;
#Column(name="user_id")
#ManyToOne
public User user;
//...
}
What am I doing wrong here? Why doesn't EBean understand my annotation?
I think you missed the #Entity annotation on the UserImage class:
#Entity
public class UserImage extends Model {
#Id
public long id;
#Constraints.Min(0)
public int index;
#Column(name="user_id")
#ManyToOne
public User user;
//...
}

JPA reusing code by extending without inheritance

I have two or more tables resembles each other.
PARENT
ID | PK
NAME | VARCHAR
CHILD
ID |PK
NAME | VARCHAR
AGE | INT
It's not #Inheritance situation because they are independent entities and related to each other by #OneToMany or #ManyToOne.
I create entity class for each other.
#Entity
public class Parent {
#Id
private Long id;
private String name;
#ManyToOne(mappedBy = "parent")
private Collection<Child> children;
}
#Entity
public class Child {
#Id
private Long id;
private String name;
private int age;
#OneToMany
private Parent parent;
}
Is there any nice way to share common fields mappings?
// #MappedSuperclass // is this what it is exactly for?
public abstract class Base {
// #Id protected Long id; // ##?
#Column(name = "name", nullable = false)
private String name;
}
#Entity
public class Parent extends Base {
#Id
#TableGenerator(...)
#GeneratedValue(...)
protected Long id;
#ManyToOne(mappedBy = "parent")
private Collection<Child> children;
}
#Entity
public class Child extends Base {
#Id
#TableGenerator(...)
#GeneratedValue(...)
protected Long id;
private int age;
#OneToMany
private Parent parent;
}
Is this OK?
Is it even possible declaring #Id protected Long id; on the Base leaving #TableGenerator and #GeneratedVAlue on extended classes?
Is there any nice way to share common fields mappings?
MappedSuperclass is exactly right tool for that.
Is it even possible declaring #Id protected Long id; on the Base
leaving #TableGenerator and #GeneratedVAlue on extended classes?
No, it is not possible.