I'm using hibernate to read my database datas but i'm having a issue with the relationship of the tables. My problems looks like that: mappedBy reference an unknown target entity property
and I read all the answers but I keep don't knowing where is the problem with my code.
Thats the class:
#Getter
#Setter
#Entity
#Table(name = "grupo_estudo_usuario")
public class EntidadeGrupoEstudoUsuario {
#Id
#Column(name = "id_grupo_estudo_usuario")
private int idGrupoEstudoUsuario;
#ManyToOne
#JoinColumn(name = "id_grupo_estudo")
private EntidadeGrupoDeEstudos idGrupoDeEstudos;
#ManyToOne
#JoinColumn(name = "id_usuario")
private EntidadeUsuario usuario;
#Column(name = "administrador")
private boolean administrador;
}
#Getter
#Setter
#Table(name = "grupo_estudo")
#Entity
public class EntidadeGrupoDeEstudos {
#Id
#Column(name = "id_grupo_estudo")
private int idGrupo;
#Column(name = "dt_atz")
private Date data;
#Column(name = "nm_grupo")
private String nomeDoGrupo;
#Column(name = "descricao")
private String descricao;
#Column(name = "privado")
private Boolean privado;
#OneToMany(mappedBy = "idGrupoDeEstudos")
private List<EntidadeGrupoDeEstudos> grupoEstudoUsuario;
}
The error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: br.com.agrupauffs.grupo.EntidadeGrupoDeEstudos.idGrupoDeEstudos in br.com.agrupauffs.grupo.EntidadeGrupoDeEstudos.grupoEstudoUsuario
And the sql script:
CREATE TABLE public.grupo_estudo (
id_grupo_estudo bigint DEFAULT nextval('public.grupo_estudo_id_seq'::regclass) NOT NULL,
dt_atz timestamp(0) without time zone,
nm_grupo character varying,
descricao character varying,
privado boolean DEFAULT true NOT NULL
);
ALTER TABLE ONLY public.grupo_estudo
ADD CONSTRAINT grupo_estudo_pk PRIMARY KEY (id_grupo_estudo);
CREATE TABLE public.grupo_estudo_usuario (
id_grupo_estudo bigint NOT NULL,
id_usuario bigint NOT NULL,
administrador boolean,
dt_atz timestamp(0) without time zone,
id_grupo_estudo_usuario bigint DEFAULT nextval('public.grupo_estudo_usuario_id_seq'::regclass) NOT NULL );
ALTER TABLE ONLY public.grupo_estudo_usuario ADD CONSTRAINT grupo_estudo_usuario_pk PRIMARY KEY (id_grupo_estudo_usuario);
ALTER TABLE ONLY public.grupo_estudo_usuario ADD CONSTRAINT grupo_estudo_usuario_fk FOREIGN KEY (id_usuario) REFERENCES public.usuario(id_usuario);
ALTER TABLE ONLY public.grupo_estudo_usuario ADD CONSTRAINT grupo_estudo_usuario_fk_1 FOREIGN KEY (id_grupo_estudo) REFERENCES public.grupo_estudo(id_grupo_estudo);
Your mappedBy should be List<EntidadeGrupoEstudoUsuario> instead of List<EntidadeGrupoDeEstudos>
#OneToMany(mappedBy = "idGrupoDeEstudos")
private List<EntidadeGrupoEstudoUsuario> grupoEstudoUsuario;
So your Entities will look like
EntidadeGrupoEstudoUsuario Entity
#Getter
#Setter
#Entity
#Table(name = "grupo_estudo_usuario")
public class EntidadeGrupoEstudoUsuario {
#Id
#Column(name = "id_grupo_estudo_usuario")
private int idGrupoEstudoUsuario;
#ManyToOne
#JoinColumn(name = "id_grupo_estudo")
private EntidadeGrupoDeEstudos idGrupoDeEstudos;
#ManyToOne
#JoinColumn(name = "id_usuario")
private EntidadeUsuario usuario;
#Column(name = "administrador")
private boolean administrador;
}
EntidadeGrupoDeEstudos Entity
#Getter
#Setter
#Table(name = "grupo_estudo")
#Entity
public class EntidadeGrupoDeEstudos {
#Id
#Column(name = "id_grupo_estudo")
private int idGrupo;
#Column(name = "dt_atz")
private Date data;
#Column(name = "nm_grupo")
private String nomeDoGrupo;
#Column(name = "descricao")
private String descricao;
#Column(name = "privado")
private Boolean privado;
#OneToMany(mappedBy = "idGrupoDeEstudos")
private List<EntidadeGrupoEstudoUsuario> grupoEstudoUsuario;
}
Related
I would like to use the Foreign key "MODEL_ID" to retrieve just one column "MODEL_NAME" from the TT_CARS table,
I tried the following code, that works but it returns the whole CARS object.
#JoinColumn(name = "MODEL_ID", referencedColumnName = "ID")
#ManyToOne(fetch = FetchType.EAGER)
private CARS cars;
Also I tried the code below, its also not working
#SecondaryTable(name = "TT_CARS", pkJoinColumns = #PrimaryKeyJoinColumn(name = "ID", referencedColumnName="MODEL_ID"))
Is there other way to retieve just the column (MODEL_NAME) using hibernate and JPA??
remarks: The modelName should be part of the Options class.
my code
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#Entity
#Table(name = "TT_OPTIONS")
public class Options {
#Id
#Column(name = "ID")
private String id;
#NotNull
#Column(name = "DESCRIPTION", nullable = false)
private String description;
#Column(name = "MODEL_ID") // Foreign key
private Long modelId;
#Column(name = "MODEL_NAME", table = "TT_CARS") // this is the column name I would like to retrieve from the TT_CARS table
private String modelName;
// getters and setters
}
You can use #Formula. It is read-only calculated column that can be retrieved by the custom subquery. It does not present in the target table.
Defines a formula (derived value) which is a SQL fragment that acts as
a #Column alternative in most cases. Represents read-only state.
Example:
#Entity
#Table(name = "TT_OPTIONS")
public class Options {
#Id
#Column(name = "ID")
private Long id;
#Column(name = "DESCRIPTION", nullable = false)
private String description;
#Column(name = "MODEL_ID")
private Long modelId;
#Formula("(select TT_CARS.MODEL_NAME from TT_CARS where TT_CARS.ID = MODEL_ID)")
private String modelNameFormula;
}
#Entity
#Table(name = "TT_CARS")
public class Cars {
#Id
#Column(name = "ID")
private Long id;
#Column(name = "MODEL_NAME")
private String modelName;
}
Hibernate generated native query:
select
options0_.id as id1_4_0_,
options0_.description as descript2_4_0_,
options0_.model_id as model_id3_4_0_,
(select
TT_CARS.MODEL_NAME
from
TT_CARS
where
TT_CARS.ID = options0_.MODEL_ID) as formula1_0_
from
tt_options options0_
where
options0_.id=?
#SecondaryTable designed for #OneToOne relationship to map multiple tables to the same entity. It will not work for the #ManyToOne relationship.
I am creating entity relationships in Spring Boot data JPA. Since those tables being legacy I am not able to modify or add columns. Issue is I am getting error if point part of embedded Id.
My entity classes looks like below:
Class Customer {
#EmbededId
private CustomerPk id;
#Column("NAME")
private String name;
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="customerDetails")
private List<Purchase> purchaseDetails;
...
}
#Embeddable
Class CustomerPk {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("PURCHASE_DATE")
private String date;
}
Purchase Entity looks like below:
Class Purchase {
#EmbededId
private PurchasePK id;
#Column("TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumns({
#JoinColumn(name="CUSTOMER_ID" referencedColumnName="CUSTOMER_ID")
#JoinColumn(name="PURCHASE_ID" referencedColumnName="PURCHASE_ID")
)}
private Customer customerDetails;
...
}
#Embeddable
Class PurchasePK {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("TRANSACTION_DATE")
private String date;
}
With above structure I am getting org.hibernate.AnnotationException: referencedColumnNames(CUSTOMER_ID, PURCHASE_ID) of Purchase.customerDetails referencing Customer not mapped to a single property.
If I remove date property from CustomerPK, I am able to make the server up. But with current requirement I need date to be part of the CustomerPK class.
I think if I use part of the composite key as Join Columns I am getting this error.
Working version:
#Entity
public class Customer {
#EmbeddedId
private CustomerPk id;
#Column(name = "NAME")
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customerDetails")
private List<Purchase> purchaseDetails;
}
#Embeddable
public class CustomerPk implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "PURCHASE_DATE")
private String date;
}
#Entity
public class Purchase {
#EmbeddedId
private PurchasePK id;
#Column(name = "TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_ID", referencedColumnName = "PURCHASE_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_DATE", referencedColumnName = "PURCHASE_DATE", insertable = false, updatable = false)
})
private Customer customerDetails;
}
#Embeddable
public class PurchasePK implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "TRANSACTION_DATE")
private String date;
}
Conclusion:
The provided information from #Ray was valid, you missed adding the required join columns to represent the full entity relation, regarding your note for the same #Ray point, yes you are right both columns usage is different but also both columns have their own name which it will not override any row value on runtime.
The result of the above tables and representation is as follows:
create table customer
(
customer_id varchar(255) not null,
purchase_date varchar(255) not null,
purchase_id varchar(255) not null,
name varchar(255),
primary key (customer_id, purchase_date, purchase_id)
);
create table purchase
(
customer_id varchar(255) not null,
transaction_date varchar(255) not null,
purchase_id varchar(255) not null,
transaction_name varchar(255),
purchase_date varchar(255),
primary key (customer_id, transaction_date, purchase_id)
);
alter table purchase
add constraint FK6rkrb8rq8x56kai7g5gm32d1y foreign key (customer_id, purchase_date, purchase_id) references customer;
I am trying to get how to write the JPA method for the class by using its foreign key instead of the primary key. Like, here I can't use findById() method, as it finds records according to primary key defined in the class. Below are the two classes for #ManyToOne and #OneToMany.
PARENT CLASS :
#Entity
#Getter
#Setter
//#Data
#NoArgsConstructor
#Table(name = "financial_plan_details", schema = "financialplanadmin")
public class FinancialPlanDao {
// This internalId is the primary key of the table.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "internal_plan_id")
private int internalId;
// This stores the plan status into the database table.
#Column(name = "plan_status")
#Size(max = 10)
private String planStatus;
#Column(name = "presentation_file_key")
#Size(max = 500)
private String presentationFileKey;
#Column(name = "create_timestamp")
#NotNull
private Timestamp createdTimestamp;
#OneToMany(mappedBy = "financialPlan")
private List<FinancialSubPlan> subPlans;
}
CHILD CLASS:
#Entity
#Getter
#Setter
#NoArgsConstructor
#Table(name = "financial_plan_subplan", schema = "financialplanadmin")
#JsonInclude(Include.NON_NULL)
public class FinancialSubPlan {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "subplan_id")
private int subPlanId;
#Column(name = "external_subplan_id")
private String externalSubplanId;
#Column(name = "is_chosen")
private Boolean subPlanIsChosen;
#ManyToOne
#JoinColumn(name = "internal_plan_id")
private FinancialPlanDao financialPlan;
}
The table generated for FinancialSubPlan will consist of the primary key column "subplan_id" and foreign key column "Internal_plan_id". So is there any way to write the JPA method to get records of FinancialSubPlan by "internal_plan_id". Also how to get this using #Query ?
It would be something like this. IDE auto-suggest would help as you type, just in case.
findFinancialSubPlanByFinancialPlanDaoId(int internalId)
or
findFinancialSubPlanByFinancialPlanDao(int internalId)
The parent PK is not being set as the FK for the child during the INSERT operation.
Here is the error:
org.postgresql.util.PSQLException: ERROR: null value in column
"workout_id" violates not-null constraint
Detail: Failing row contains (20ea52e3-0491-480f-b3c1-b1da70feee8f,
null, null, 510, 55, KG, Olympic).
In this case, only one ID is generated, and that is for the child. The parent ID is never created, and thus the FK constraint is broken and the DB transaction fails.
To troubleshoot this issue, I removed the child from the parent, and a UUID is indeed generated for the parent.
In the example below, Workout is the parent, and Set is the child. Also shown is the endpoint where the persistence operation is executed.
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "workouts")
public class Workout implements Serializable {
#Id
#Type(type = "pg-uuid")
#GeneratedValue(generator="UUID")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private UUID id;
#Column(name="user_id")
private long user; // todo use UUID
#Column(name="name")
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "workout")
//#JoinColumn(columnDefinition="uuid", name = "workout_id")
private List<Set> set;
#Column(name="start_time")
private String startTime;
#Column(name="stop_time")
private String stopTime;
#Column(name="notes")
private String notes;
}
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "exercise_sets")
public class Set {
#Id
#Type(type = "pg-uuid")
#GeneratedValue(generator="UUID")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private UUID id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="workout_id")
private Workout workout;
#Column(name="reps")
private Integer numberOfReps;
#Column(name="weight")
private Integer weightLifted;
#Column(name="unit")
private String weightUnit;
#Column(name="bar_type")
private String barType;
}
#RequestMapping(value="/user/{id}", method=RequestMethod.POST)
public ResponseEntity<Object> addWorkoutForUser(#PathVariable(name="id") long id) {
Set s = Set.builder()
//.workout(w)
//.workoutId(1)
.numberOfReps(10)
.weightLifted(25)
.weightUnit("KG")
.barType("Olympic").build();
Set s2 = Set.builder()
//.workout(w)
//.workoutId(1)
.numberOfReps(510)
.weightLifted(55)
.weightUnit("KG")
.barType("Olympic").build();
Workout w = Workout.builder()
.set(Arrays.asList(s2,s))
.name("My First Workout")
.notes("Felt great")
.startTime("now")
.stopTime("later").build();
Workout persistedData = this.workoutDao.save(w);
return ResponseEntity.ok(persistedData);
}
Greetings to the community,
I am struggling all day to find a solution to the issue below.
The scenario is the following, I have a table
---TABLE_ONE---
INT ID
VARCHAR NAME
PRIMARY_KEY (ID)
and my other table consisted of three columns which consist together a composite key
---TABLE_TWO---
INT TABLE_ONE_ID (FK -> TABLE_ONE.ID)
VARCHAR NAME
VARCHAR EMAIL
PRIMARY_KEY(TABLE_ONE_ID, NAME, EMAIL)
The relationship I want to achieve is that the TABLE_ONE entity will
have a list of objects from the TABLE_TWO (one-to-many relationship).
I tried to do this with as shown below.
#Entity
#Table(name = "TABLE_ONE")
public class TableOne {
#Column(name="id")
private int id;
#Column(name="name")
private String name
#OneToMany(fetch = FetchType.EAGER, mappedBy = "tableOne")
private List<TableTwo> tableTwoList;
//getters, setters, constructors
}
#Entity
#Table(name = "TABLE_TWO")
public class TableTwo {
#EmbeddedId
private TableTwoCompositeId tableTwoCompositeId;
#ManyToOne
#JoinColumn(name = "TABLE_ONE_ID", referencedColumnName = "ID", insertable = false, updatable = false)
private TableOne tableOne;
//getters, setters, constructors
}
#Embeddable
public class TableTwoCompositeId {
#Column(name = "TABLE_ONE_ID")
public Integer provider;
#Column(name = "NAME")
public String name;
#Column(name = "EMAIL")
public String email;
//getters, setters, constructors
}
However, I'm getting javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet and Caused by: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist when a TableOne object is retrieved from the database.
Thanks in advance for any help!
I think you need several minor changes:
TableOne.id needs an #Id annotation
The type of TableTwoCompositeId.provider should match the type of TableOne.id
TableTwo.tableOne needs a #MapsId annotation to indicate it maps TableTwoCompositeId.provider
Here is how the code should look:
#Entity
#Table(name = "TABLE_ONE")
public class TableOne {
#Id
#Column(name="id")
private int id;
#Column(name="name")
private String name
#OneToMany(fetch = FetchType.EAGER, mappedBy = "tableOne")
private List<TableTwo> tableTwoList;
//getters, setters, constructors
}
#Entity
#Table(name = "TABLE_TWO")
public class TableTwo {
#EmbeddedId
private TableTwoCompositeId tableTwoCompositeId;
#MapsId("provider") // maps provider attribute of embedded id
#ManyToOne
#JoinColumn(name = "TABLE_ONE_ID", referencedColumnName = "ID", insertable = false, updatable = false)
private TableOne tableOne;
//getters, setters, constructors
}
#Embeddable
public class TableTwoCompositeId {
#Column(name = "TABLE_ONE_ID")
public int provider;
#Column(name = "NAME")
public String name;
#Column(name = "EMAIL")
public String email;
//getters, setters, constructors
}