Double abstract class inheritance and failed to create sessionFactory (hibernate) - java

I'm working on Hibernate and i need two abstract classes. First one, Product is the main one and there should be no table on the database named product. Second abstract class is ComPart(inherited from Product) and some computer parts like gpu and cpu are inherited from this class. There should be only one table named com_part and both CPUs and GPUs should be in this table(table per hierarchy).
#MappedSuperclass
public abstract class Product{
private long pID;
protected String manufacturer;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "PID", unique = true, nullable = false)
public int getPID() {
return pID;
}
#Column(name = "Manufacturer")
public String getManufacturer() {
return manufacturer;
}
}
// computer part abstract class inherited from Product
#Entity
#Table(name = "com_part")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="disc",
discriminatorType=DiscriminatorType.STRING
)
#AttributeOverrides({
#AttributeOverride(name="manufacturer", column=#Column(name="Manufacturer"))
})
public abstract class ComPart extends Product {
private String platform;
#Column(name = "PLATFORM", length = 10)
public String getPlatform() {
return platform;
}
}
// Various computer hardwares inherited from ComPart
#Entity
#Table(name="com_part")
#DiscriminatorValue("CPU")
public class Processor extends comPart {
private String socketType;
private String chipset;
//getters setters...
}
#Entity
#Table(name="com_part")
#DiscriminatorValue("GPU")
public class GraphicsCard extends comPart {
private double memory;
//getters setters...
}
How can i map all these features? Above code even can't create sessionfactory?! it generates these errors:
Failed to create sessionFactory object.java.lang.NullPointerException
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.bts.core.hb.HibernateUtil.<clinit>(HibernateUtil.java:35)
and
Caused by: java.lang.NullPointerException
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1424)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1351)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1733)
at com.bts.core.hb.HibernateUtil.<clinit>(HibernateUtil.java:32)

Related

#ElementCollection setField throws SQLSyntaxErrorException: ORA-00942

I have 2 java classes, one of them contains the other as a list by #ElementCollection.
When I try to set that list, following error occurs:
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
Error Code: 942
Call: SELECT t0.VERSIONS FROM MainProcess_VERSIONS t0 WHERE (t0.MainProcess_SUBJECT_ID = ?)
bind => [#id]
Query: DirectReadQuery(name="versions" sql="SELECT t0.VERSIONS
FROM MainProcess_VERSIONS t0 WHERE (t0.MainProcess_SUBJECT_ID = ?)")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:683)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526)
.
.
.
at ...Editor.MAINPROCESS._persistence_propertyChange(MAINPROCESS.java)
at ...Editor.MAINPROCESS._persistence_set_versions(MAINPROCESS.java)
at ...MAINPROCESS.setVersions(MAINPROCESS.java:79)
at ...DataModel.fillSubprocessSubject(DataModel.java:643)
at ...DataModel.load(DataModel.java:321)
If I remove the #ElementCollection then I get the following error
Error Code: 942
Call:
SELECT t1.ACT_VERSION, t1.SUBJECT_ID, t1.ACT_VERSION_REMARK,
t1.ACT_VALID_TO, t1.ACT_VERSION_ACCEPTED, t1.NORMALRETURNVALUES, t1.ACT_VALID_FROM
FROM MAINPROCESS_MAINPROCESSVERSION t0, MAINPROCESSVERSION t1
WHERE ((t0.MainProcess_SUBJECT_ID = ?) AND ((t1.SUBJECT_ID = t0.SUBJECT_ID)
AND (t1.ACT_VERSION = t0.ACT_VERSION)))
bind => [#id]
Here are my classes,
MainProcess:
#Entity
public class MainProcess implements Serializable {
#Id
#Column(name = "SUBJECT_ID", nullable = false)
private Long subjectId;
...other columns
#ElementCollection
private List<MainProcessVersion> versions = new ArrayList<MainProcessVersion>();
public MainProcess() {
}
public void setVersions(List<MainProcessVersion> versions) {
this.versions = versions;
}
public List<MainProcessVersion> getVersions() {
return versions;
}
other getters and setters...
}
MainProcessVersion:
#Entity
#IdClass(MainProcessVersionPK.class)
public class MainProcessVersion implements Serializable {
#Id
#Column(name = "SUBJECT_ID", nullable = false)
#XmlTransient
private Long subjectId;
#Id
#Column(name = "ACT_VERSION")
private Long actVersion;
...other columns
private List<String> normalReturnValues;
public MainProcessVersion() {
}
getters and setters...
}
And the function in which the error occurs:
private MainProcess fillSubprocessSubject(Long Id) {
MainProcess p = someFacade.getProcess(Id);
List<MainProcessVersion> versions = someFacade.getProcessVersions(Id);
p.setVersions(versions); //error is here
return p;
}
Thanks in advance for any help.
I managed to solve my problem. Most important was to understand the difference between #ElementCollection and #OneToMany annotation. I cannot better explain like this.
So the problem was that my MainProcessVersion.java was annotated with #Entity, thus I could not add the #ElementCollection annotation to it in the MainProcess.java.
#ElementCollection //One cannot use this annotation because MainProcessVersion is an entity.
private List<MainProcessVersion> versions = new ArrayList<MainProcessVersion>();
But I need the Entity, so I created resultRow class wich is the same as my Entity class except the annotation. After query selection, I cast my result to my new resultRow class and I can set that list in the MainProcess.java.
My resultRow class:
public class MainProcessVersionResultRow implements Serializable {
private Long subjectId;
...other code
}
My old MainProcess class
#Entity
public class MainProcess implements Serializable {
#Id
#Column(name = "SUBJECT_ID", nullable = false)
private Long subjectId;
...other columns
//without #ElementCollection and the new resultRow object type
private List<MainProcessVersionResultRow> versions = new ArrayList<MainProcessVersionResultRow>();
public MainProcess() {
}
...getters. setters
}
And then, I "cast" my entity to resultRow class:
private MainProcess fillSubprocessSubject(Long subjectId) {
MainProcess p =
someFacade.getSubprocessSubject(subjectId);
List<MainProcessVersion> versions = someFacade.getProcessVersions(subjectId);
List<MainProcessVersionResultRow> versionResultRows = new ArrayList<MainProcessVersionResultRow>();
for (MainProcessVersion vs : versions) {
MainProcessVersionResultRow versionSingleResultRow = new MainProcessVersionResultRow(vs);
versionSingleResultRow.setNormalReturnValues(processReturnValues(p.getSubjectId(), vs.getActVersion()));
versionResultRows.add(versionSingleResultRow);
}
p.setVersions(versionResultRows); //does not throw an error any more
return p;
}
So conclusion:
Do not use #ElementCollection on a class that has an #Entity annotation.

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.

Loading of Properties from database in Hibernate?

I have three classes having class hierarchy as
ParentClass.java
having commons properties used for both ChildClass1 and ChildClass2.
ChildClass1 extends ParentClass
having properties used for this ChildClass1 + it also use some of the common properties from parent class
ChildClass2 extends ParentClass
having properties used for this ChildClass2 + it also use some of the common properties from parent class
This all properties are available into table with two columns
**Key value** Type
---------------------------------------
propertyKey1 propertyValue1 Child1
propertyKey2 propertyValue2 Child1
propertyKey3 propertyValue3 Child2
propertyKey4 propertyValue4 Child2
propertyKey5 propertyValue5 CommonPorperty
.. .. ..
propertyKeyn propertyValuen ..
Now I am not sure that how to load them from hibernate inheritance ?
Apology for silly question...
Thanks in advance
You need to put an additional column 'Discriminator' to inform Hibernate which instance should be loaded when you're working on same table with multiple types.
See example:
#Entity
#org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
#Table(name = "PARENT_TABLE")
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class ParentEntity implements java.io.Serializable {
private long id;
private String commonValue1;
#Id
#Column(name = "ID", nullable = false)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "Common_Value1")
public String getCommonValue1(){
return commonValue1;
}
public void setCommonValue1(String commonValue1){
this.commonValue1 = commonValue1;
}
}
#Entity
#DiscriminatorValue("1")
public class ChildEntity1 extends ParentEntity {
private String child1Value;
#Column(name = "Child1_Value")
public String getChild1Value(){
return child1Value;
}
public void setChild1Value(String child1Value){
this.child1Value = child1Value;
}
}
#Entity
#DiscriminatorValue("2")
public class ChildEntity2 extends ParentEntity {
private String child2Value;
#Column(name = "Child2_Value")
public String getChild2Value(){
return child2Value;
}
public void setChild2Value(String child2Value){
this.child2Value = child2Value;
}
}

Hibernate storing identifiers of another entities not whole entities?

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.

Categories