Hibernate storing identifiers of another entities not whole entities? - java

I'm building RESTful service on java using JERSEY and need to implement relationships between entities storing just identifier on another entity not whole. Is there any way to implements it in the hibernate?
I'm using something like this but it is not working.
#Entity
#javax.persistence.Table(name = "manager_user")
public class ManagerUser extends User {
#ManyToOne(targetEntity = ShopAdminUser.class)
private Integer shopAdminUserId;
//...
}
#Entity
#javax.persistence.Table(name = "shop_admin_user")
public class ShopAdminUser extends User {
#Lob
private String contactData;
public String getContactData() {
return contactData;
}
public void setContactData(String contactData) {
this.contactData = contactData;
}
}
#Entity
#Inheritance(strategy= InheritanceType.TABLE_PER_CLASS)
public abstract class User {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
//...
}
It will be very comfortable for me to implement this.

Related

About inheritance mapping and best practices in Java

I'm learning about the ways of mapping inheritance from database to java with JPA/Hibernate. I've found several examples of how to do it, but not how to apply it.
Now, I'm trying to apply this knowledge on a small project, but I run into a problem where I can't do it the way I thought it would be ideal.
About the code below, the problem is: I have an "Expense" class that records a new expense (credit card debt, etc.), this debt has a creditor, which can be a person (PF) or institution (PJ). A expense has only one creditor, but I'm forced to model with one of each subclass.
#Data
#Entity
#Table(name = "expense")
public class Expense {
// CODE
#ManyToOne
#JoinColumn(name = "creditorPF")
private CreditorPF creditorPF;
#ManyToOne
#JoinColumn(name = "creditorPJ")
private CreditorPJ creditorPJ;
}
#Data
#Entity
#Table(name = "creditor")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Creditor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idCreditor")
protected Long id;
#NonNull
protected String description;
}
#Getter
#Setter
#Entity
#Table(name = "creditor_pf")
#PrimaryKeyJoinColumn(name = "idCreditor")
public class CreditorPF extends Creditor {
private String cpf;
#Builder
public CreditorPF() {
super("");
}
#Builder
public CreditorPF(String cpf, String nome) {
super(nome);
this.cpf = cpf;
}
}
#Getter
#Setter
#Entity
#Table(name = "creditor_pj")
#PrimaryKeyJoinColumn(name = "idCreditor")
public class CreditorPJ extends Creditor {
private String cnpj;
#Builder
public CreditorPJ(String cnpj, String nome) {
super(nome);
this.cnpj = cnpj;
}
#Builder
public CreditorPJ() {
super("");
}
}
This works fine, but I don't think it's a good design, because the design is allowing one more creditor per subclass, even if I add validations to prevent it, the design would be semantically incorrect.
Is there a way I can get a design like this code below, but that I can get the subclass information when I retrieve the object through hibernate?
#Data
#Entity
#Table(name = "expense")
public class Expense {
// CODE
#ManyToOne
#JoinColumn(name = "creditor")
private Creditor creditor;
}
In case of getting the Credit type from THROUGH the Expense Object ,there's no way besides using instanceof or getClass() as #Chris said ,btw it's preferable to use composition over inheritence,since it doesn't introduce this problem and preserves database consistency since you can"t be FORCED to have nullable fields, and in your case you can implement it using a class Creditor containing an enum which holds the creditor type since it's know to you ,hope this helps !

querydsl how to return dto list?

i use querydsl, hibernate
i want select data by Dto in Dto list but not working
here is my code
#Data
#Entity
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
#Entity
#Setter
public class Member {
#Id
#GeneratedValue
private Long id;
private String name;
#ManyToOne
#JoinColumn(name = "team_id")
private Team team;
}
#Setter
public class TeamDto {
private Long id;
private String name;
private List<MemberDto> members = new ArrayList<>();
}
#Setter
public class MemberDto {
private Long id;
private String name;
}
test
#BeforeEach
void setup() {
queryFactory = new JPAQueryFactory(em);
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member("memberA");
member.setTeam(team);
em.persist(member);
Member member2 = new Member("memberB");
member2.setTeam(team);
em.persist(member2);
em.flush();
em.clear();
}
#Test
void t1() {
TeamDto teamDto = queryFactory
.select(Projections.fields(
TeamDto.class,
team.id,
team.name,
Projections.fields(
MemberDto.class,
member.id,
member.name
).as("members")
))
.from(team)
.fetchOne();
System.out.println("teamDto = " + teamDto);
}
error log is = java.lang.IllegalArgumentException: com.blog.querydsltest.domain.dto.MemberDto is not compatible with java.util.List
what is problem?? is impossible bring data by List dto??
i try to change Projections.fields to bean, construct, ... but not working
how can i do ?
Multi level aggregations are currently not supported by QueryDSL. There are also no concrete plans to support it as of now.
For a DTO solution that can fetch associations with it, I recommend you to have a look at Blaze-Persistence Entity Views. With Entity Views the code for your DTO would look something like the following:
#EntityView(Team.class)
public interface TeamDto {
#IdMapping public Long getId();
#Mapping("name") public String getName();
#Mapping("members") public List<MemberDTO> getMembers();
}
If members is not an association on your TeamEntity, you can map it through a #MappingCorrelated binding.
Disclaimer: I am a contributor for Hibernate, QueryDSL and Blaze-Persistence.

Does extending a base class and both classes having #Id annotation cause Repeated column in mapping for entity?

I have two classes.
One class extends the other.
Both classes will be persisted in the database.
Why am I still getting : Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.ct.www.model.Bt column: q_Id (should be mapped with insert="false" update="false")
Questions.class
#Entity
#Table(name="Questions")
#Access(value = AccessType.FIELD)
public class Questions implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
//#Access(value= AccessType.FIELD)
private String q_Id;
#Column(name="q_type")
private String q_Type;
#Column(name="q_lang")
private String q_lang;
#Access(value = AccessType.PROPERTY)
public String getQ_Type() {
return q_Type;
}
public void setQ_Type(String q_Type) {
this.q_Type = q_Type;
}
#Id
#Column(name="q_Id")
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2", strategy = "uuid2")
#Access(value = AccessType.PROPERTY)
public String getQ_Id() {
return q_Id;
}
public void setQ_Id(String q_Id) {
this.q_Id = q_Id;
}
#Access(value = AccessType.PROPERTY)
public String getQ_lang() {
return q_lang;
}
public void setQ_lang(String q_lang) {
this.q_lang = q_lang;
}
}
BT.class
#Entity
#Table(name="BT")
#Access(value = AccessType.FIELD)
public class BT extends Questions implements Serializable{
private static final long serialVersionUID = 1L;
#Access(value = AccessType.FIELD)
// #Id
// #Column(name="q_Id")
private String q_Id;
#Access(value = AccessType.PROPERTY)
public String getQ_Id() {
return q_Id;
}
public void setQ_Id(String q_Id) {
this.q_Id = q_Id;
}
// #OneToOne(cascade = CascadeType.ALL)
// #PrimaryKeyJoinColumn
// #JoinColumn(name="q_id")
// #MapsId
private Questions question;
public Questions getQuestion() {
return question;
}
public void setQuestion(Questions question) {
this.question = question;
}
}
One of my use case is
Questions and BT will be persisted separately into corresponding tables in MySQL (Questions table and BT table).
BT is a type of Question. So I decided to extend it.
Both table has a primary key which is Id, and my DAO class will first insert in Questions table and use same Id for BT class which later inserts into BT table.
Extending a base class which is an Entity will cause this problem.
You can:
Remove the common mapped fields/properties from the child class
Add #Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) above parent class for your use case.
Refer to Section 2.11.4 in Hibernate-5.3.1.Final User Guide for example code.
If you need different generation strategy in parent and child, you can override the getQ_Id() method in child and implement that.

Difficulty creating relationship with abstract class and embedded attribute with JPA/Hibernate

I'm trying, but have not been successful so far, using the following classes with Hibernate.
#MappedSuperclass
#Embeddable
public abstract class Foo {
// atributes...
}
#Embeddable
public class Poo extends Foo {
// atributes...
}
#Entity
#Table
public class None {
// atributes...
#Embedded
private Foo foo;
// constructor
public None(Foo foo) {
this.foo = foo;
}
}
// example of save
None none = new None(Poo poo);
save(none);
Hibernate returns: Cannot instantiate abstract class or interface
Is it possible to perform this operation with JPA?
I ran into the same problem.
It seems like #embedable does not work with #DiscriminatorColumn. The only way I could get this to work is to use #DiscriminatorColumn, but treat the #embedable like a separate entity on the same table.
What this means is that the query will likely join the table to itself.
#Entity
#Table(name="tbComputers")
public class Computer{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long id;
public String motherboard;
#OneToOne
#JoinColumn(name="id")
public CPU cpu;
}
#Entity
#DiscriminatorColumn(name="cpu_type")
#Table(name="tbComputers")
public abstract class CPU {
#Id
private Long id;
#Column(name = "cpu")
public String name;
public abstract String someProcessorSpecificMethod();
}
#Entity
#DiscriminatorValue("Intel")
public class Intel extends CPU {
#Override
public String someProcessorSpecificMethod() {
return "Intel";
}
}
#Entity
#DiscriminatorValue("AMD")
public class AMD extends CPU {
#Override
public String someProcessorSpecificMethod() {
return "AMD";
}
}
EDIT: After further testing I found that while this works for reading data, it does not for persisting. It will create a separate INSERT. It seems like it is not supported https://hibernate.atlassian.net/browse/HHH-1910. The alternative is to to split the table.

Jpa 2.0 - EntityManager.find (SomeEntity.class,PK) need to fill Descriminator value to key

I have a problem, I have two entity Job and JobPK
Job class looks like this sample code :
#Entity
#IdClass(JobPK.class)
#Table(name="JOB")
#Inheritance
#DiscriminatorColumn(name="JOB_TYPE")
public abstract class Job implements Serializable {
#Id
#Column(name="FOLDER_ID")
private BigDecimal folderId;
#Id
#ColumnDefinition(position = 1)
private String name;
#Column(name="JOB_TYPE",insertable=false,updatable=false)
private String jobType;
...
}
and JobPk :
public class JobPK implements Serializable {
private static final long serialVersionUID = -3266336718203527905L;
#Column(name="JOB_TYPE",insertable=false,updatable=false)
private String jobType;
#Id
private String name;
#Id
#Column(name="FOLDER_ID")
private BigDecimal folderId;
......
}
I have two class which extends Job : CalculatingJob and ImportingJob
Now I wont to use :
getEntityManager().find(CalculatingJob.class, new JobPK (BigDecimal.valueOf(folderId),name))
and I have problem because I must fill i JobPK descriminator value field. If I don't do that I've got Null Pointer Exception. Descriminator value is in key by default I think but I don't want put information about descriminator value explicite during JobPk creating. I thought that Entity which extends from Job will fill this field automaticaly. Any Idea to bypass this problem, maybe I can get Annotation #DescriminatorVale from CalculatingJob and then put into constructor JobPk
Thanks for Help
Try this configuration for Hierarchy structure
Job.java
#Table(name = "JOB")
#Inheritance
#IdClass(JobPK.class)
#DiscriminatorColumn(name = "JOB_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class Job implements java.io.Serializable {
}
CalculatingJob.java
#Entity
#DiscriminatorValue("CalculatingJob")
public class CalculatingJob extends Job {
}
ImportingJob.java
#Entity
#DiscriminatorValue("ImportingJob")
public class ImportingJob extends Job {
}
JobPK.java
public class JobPK implements Serializable {
}
The discriminator value is entered by hibernate.

Categories