Problems in relationships between tables in JPA - java

I'm a little new to JPA and I'm trying to get my entity classes to work properly, but my code is always returning me this error: "Multiple writable mappings exist for the field [PRODUTOS.MARCA_IDMARCA]"
These are my entity classes:
#Entity
public class Marca implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer idMarca;
private String nome;
private Integer idFornecedores;
.
.
.
}
I'm trying to make an unidirectional ManyToOne relationship between produtos and Marca (1 Marca to Many produtos):
#Entity
public class produtos implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long idProdutos;
private int codBarras;
private String nome;
private float preco;
private int qtdProduto;
private int idCategoriaProduto;
#ManyToOne
private CategoriaProduto categoria;
private int Marca_idMarca;
#ManyToOne
private Marca marca;
.
.
.
}
Error:
Exception Description: Multiple writable mappings exist for the field [PRODUTOS.MARCA_IDMARCA]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[marca]
Descriptor: RelationalDescriptor(ClassesDeEntidade.produtos --> [DatabaseTable(PRODUTOS)])
I really don't know what's happening. Can anyone explain to me why this code is wrong?
EDIT:
Table definitions:
Produtos:
CREATE TABLE IF NOT EXISTS mydb.Produtos (
idProdutos INT NOT NULL AUTO_INCREMENT,
codBarras INT(13) NOT NULL,
nome VARCHAR(150) NOT NULL,
preco FLOAT NOT NULL,
qtdProduto INT NOT NULL,
idCategoriaProduto INT NOT NULL,
Marca_idMarca INT NOT NULL,
PRIMARY KEY (idProdutos),
INDEX fk_Produtos_CategoriaProduto1_idx (idCategoriaProduto ASC),
INDEX fk_Produtos_Marca1_idx (Marca_idMarca ASC),
CONSTRAINT fk_Produtos_CategoriaProduto1
FOREIGN KEY (idCategoriaProduto)
REFERENCES mydb.CategoriaProduto (idCategoriaProduto)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_Produtos_Marca1
FOREIGN KEY (Marca_idMarca)
REFERENCES mydb.Marca (idMarca)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Marca:
CREATE TABLE IF NOT EXISTS mydb.Marca (
idMarca INT NOT NULL AUTO_INCREMENT,
nome VARCHAR(45) NOT NULL,
idFornecedores INT NOT NULL,
PRIMARY KEY (idMarca),
INDEX fk_Marca_Fornecedores1_idx (idFornecedores ASC),
CONSTRAINT fk_Marca_Fornecedores1
FOREIGN KEY (idFornecedores)
REFERENCES mydb.Fornecedores (idFornecedores)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

Can you show your table definitions?
The problem seems to be that you have two fields (probably Marca marca, which have the #ManyToOne annotation and int Marca_idMarca, that has the same name) mapping to the same PRODUTO.ID_MARCA column in the database.
I know I should post this as a comment, but I'm not able to comment yet.

Related

How to fix "Unable to find column with logical name" in Java, Hibernate

I'm getting the error "Unable to find column with logical name: dniNumeros in org.hibernate.mapping.Table(alumno) and its related supertables and secondary tables" when using IdClass
I have tried using an EmbeddedId instead and I'm getting the same error. The column obviously exists in my database, because the code works perfectly fine when I remove the IdClass line from it
#Entity
#Table(name="dificultadalumnoejercicio")
#IdClass(DificultadAlumnoEjercicioPK.class)
public class DificultadAlumnoEjercicio implements Serializable {
private static final long serialVersionUID = -111454640507305257L;
#Id
#ManyToOne(cascade=CascadeType.MERGE)
#JoinColumns ({
#JoinColumn(name="alumnoDNINumeros", referencedColumnName="dniNumeros"),
#JoinColumn(name="alumnoDNILetra", referencedColumnName="dniLetra")
})
private Alumno alumno;
#Id
#OneToOne(cascade=CascadeType.MERGE)
#JoinColumn(name="ejercicioID", referencedColumnName="id")
private Ejercicio ejercicio;
#ManyToOne(cascade=CascadeType.MERGE)
#JoinColumn(name="dificultadID", referencedColumnName="id")
private Dificultad dificultad;
// Constructors / Getters / Setters
}
And here's my IdClass
#Embeddable
public class DificultadAlumnoEjercicioPK implements Serializable {
private static final long serialVersionUID = 5559503979252689702L;
public Alumno alumno;
public Ejercicio ejercicio;
// Constructors / Getters / Setters
}
Here is my database code:
CREATE TABLE `dificultadAlumnoEjercicio` (
`alumnoDNINumeros` CHAR(8),
`alumnoDNILetra` CHAR,
`ejercicioID` INT,
`dificultadID` INT NOT NULL,
PRIMARY KEY (alumnoDNINumeros, alumnoDNILetra, ejercicioID),
FOREIGN KEY (alumnoDNINumeros, alumnoDNILetra) REFERENCES alumno(dniNumeros, dniLetra),
FOREIGN KEY (dificultadID) REFERENCES dificultad(id),
FOREIGN KEY (ejercicioID) REFERENCES ejercicio(id)
);
CREATE TABLE `alumno` (
`dniNumeros` CHAR(8),
`dniLetra` CHAR,
PRIMARY KEY (dniNumeros, dniLetra),
FOREIGN KEY (dniNumeros, dniLetra) REFERENCES persona(dniNumeros, dniLetra)
);

entitymanger.find executing find query by using primary key of foreign key

I want to get an object of EventDate using primary key. Following is the query i'm executing
EventData eventData = entityManager.find(EventData.class, eventdataid);
After executing this command in console i'm getting the query as
select eventsajgj0_.FILE_ID as FILE_ID8_14_0_, eventsajgj0_.id as
id1_12_0_, eventsajgj0_.id as id1_12_1_, eventsajgj0_.CODE as CODE2_12_1_,
eventsajgj0_.DATE as DATE3_12_1_, eventsajgj0_.FILE_ID as FILE_ID8_12_1_,
eventsajgj0_.MILLIS as MILLIS4_12_1_, eventsajgj0_.ORDER_NR as
ORDER_NR5_12_1_, eventsajgj0_.TYPE as TYPE6_12_1_, eventsajgj0_.VALUE as
VALUE7_12_1_ from eventdata eventsajgj0_ **where eventsajgj0_.FILE_ID=?**
order by eventsajgj0_.ORDER_NR
Please note the where clause in above query is against file_id(foreign key) and not id(eventdata primary key)
The dao structure is as follows
public class EventData implements Serializable {
private static final long serialVersionUID = 1L;
public EventData() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="FILE_ID")
private ApplicationFile file;
getter & setters
}
public class ApplicationFile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
bi-directional many-to-one association to Event
#OneToMany(mappedBy="file", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#OrderBy("orderNr")
private List<EventData> eventsajgjd;
getter & setters
}
my question is, why is it querying using file_id and not id when i'm executing a query on eventdata table.
PS:if i change fetch type of ApplicationFile as LAZY then the query executed is on id and not on file_id.
(added from Comment:)
CREATE TABLE eventdata (
ID int(11) NOT NULL AUTO_INCREMENT,
FILE_ID int(11) DEFAULT NULL,
PRIMARY KEY (ID),
KEY eventdata_ibfk_1 (FILE_ID),
CONSTRAINT eventdata_ibfk_1 FOREIGN KEY (FILE_ID)
REFERENCES files (ID) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=297502 DEFAULT CHARSET=utf8
I bet because you mapped the EventData / ApplicationFile bidirectionally (you have an attribute of type List<EventData> in ApplicationFile entity
So loading an EventData means eagerly loading the related ApplicationFile and so eagerly loading all related EventData.
I suppose that the related ApplicationFile instance is already in EntityManager L1 cache (otherwise the query should join on files table)

How to implement Composite Primary key and Composite Foreign Key using JPA,Hibernate, Springboot

I searched a lot for this particular problem but i didn''t find any specific solution. I have a Composite Primary Key in one table and one of the field from this composite primary key is the part of the Composite Primary Key of another table. You can say that this particular field is the foreign key in the second table but i a not defining any exclusive Foreign Key constraint in the table definition. There can be multiple Records in the second table for each rec in the first table.i am trying to implement this using SPringBoot-JPA-Hibernate but not being able to do so. Can some body help me here. Here are the detais:-
I have a USER_CREDENTIAL table with following fields:-
CREATE TABLE `INSTITUTION_USER_CREDENTIAL` (
`INSTITUTION_USER_ID INT(10) NOT NULL, -> AutoGeneratd
`INSTITUTION_USER_NAME` VARCHAR(50) NOT NULL,
`INSTITUTION_USER_PASSWORD` VARCHAR(50) NOT NULL,
`FIRST_NAME` VARCHAR(100) NOT NULL,
`MIDDLE_NAME` VARCHAR(100),
`LAST_NAME` VARCHAR(100) NOT NULL,
PRIMARY KEY (`INSTITUTION_USER_ID`,`INSTITUTION_USER_NAME`)
);
2) Here is my second table
CREATE TABLE `INSTITUTION_USER_CREDENTIAL_MASTER` (
`INSTITUTION_ID` INT(10) NOT NULL, -> Autogenerated
`INSTITUTION_USER_ID` INT(10) NOT NULL, -> Coming from
INSTITUTION_USER_CREDENTIAL
`INSTITUTION_USER_ROLE` CHAR(02) NOT NULL,
`INSTITUTION_USER_STATUS` CHAR(02) NOT NULL,
`INSTITUTION_NAME` VARCHAR(200) NOT NULL,
`LAST_UPDT_ID` VARCHAR(100) NOT NULL,
`LAST_UPDT_TS` DATETIME NOT NULL,
PRIMARY KEY(`INSTITUTION_ID`,`INSTITUTION_USER_ID`,`INSTITUTION_USER_ROLE`)
);
Note that i haven't declare any particular foreign key in the second table. I have two #Embeddable Class corresponding to two primary key structure for two different table:-
For the INSTITUTION_USER_CREDENTIAL table:-
#Embeddable
public class InstitutionUserCredentialPrimaryKey implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_USER_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionUserId;
#Column(name = "INSTITUTION_USER_NAME")
private String institutionUserName;
//Getter-Setters removed for clarity
}
Corresponding Entity Class:-
#Entity(name = "INSTITUTION_USER_CREDENTIAL")
public class InstitutionUserCredential {
#EmbeddedId
private InstitutionUserCredentialPrimaryKey
institutionUserCredentialPrimaryKey;
#Column(name = "INSTITUTION_USER_PASSWORD")
private String instituteUserPassword;
#Column(name = "FIRST_NAME")
private String firstname;
#Column(name = "MIDDLE_NAME")
private String middleName;
#Column(name = "LAST_NAME")
private String lastName;
#OneToMany(mappedBy="institutionUserCredential", cascade = CascadeType.ALL)
private List<InstitutionUserCredentialMaster>
institutionUserCredentialMaster;
//Getter-Setter and other part of the code removed for clarity
}
For the INSTITUTION_USER_CREDENTIAL_MASTER table:-
#Embeddable
public class InstituteUserCredentialMasterPrimaryKey implements Serializable
{
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionId;
#Column(name = "INSTITUTION_USER_ID")
private int institutionUserId;
#Column(name = "INSTITUTION_USER_ROLE")
private String userRole;
//Getter-Setter and other part of the code removed for clarity
}
Entity Class:-
#Entity(name = "INSTITUTION_USER_CREDENTIAL_MASTER")
public class InstitutionUserCredentialMaster {
#EmbeddedId
private InstituteUserCredentialMasterPrimaryKey
instituteUserCredentialMasterPrimaryKey;
#Column(name = "INSTITUTION_USER_STATUS")
private String userStatus;
#Column(name = "INSTITUTION_NAME")
private String institutionName;
#Column(name = "LAST_UPDT_ID")
private String lastUpdateId;
#Column(name = "LAST_UPDT_TS")
private String lastUpdateTimestamp;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="institutionUserId", referencedColumnName =
"INSTITUTION_USER_ID")
})
private InstitutionUserCredential institutionUserCredential;
//Getter-Setter and other part of the code removed for clarity
}
Note that only 1 field INSTITUTION_USER_ID, is getting used in the Composite PrimaryKey of the InstitutionUserCredentialMaster and is coming from the composite primary key of the InstitutionUserCredential.
When i am running my code this is giving me an error like :-
Invocation of init method failed; nested exception is
org.hibernate.AnnotationException:
referencedColumnNames(INSTITUTION_USER_ID) of com.bnl.application.entity.InstitutionUserCredentialMaster.institutionUserCredential referencing com.bnl.application.entity.InstitutionUserCredential not mapped to a single property
None of the examples i have seen so far involving the Composite Primary key and foreign key doesn't treat any one particular field and is more of the entire key structure. I am using MYSQL and i have checked that we can create table having composite primary key and one of the field from that composite key is foreign key in another table and also part of the Composite Primary key of the second table.
Any pointers appreciated
UPDATE:- In my first post i made a mistake while posting it. I am sorry that institutionUserName became a part of the InstitutionUserCredentialMaster. it was a typo. There is no existence of the intitutionUserName in the InstitutionUserCredentialMaster table. i have fixed that and updated the post.
***** Update based on the input by Niver and Wega *****
Update to the InstitutionUserCredentialMasterPrimaryKey
#Embeddable
public class InstituteUserCredentialMasterPrimaryKey implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionId;
#Column(name = "INSTITUTION_USER_ID")
private int institutionUserId;
// Added the institutionUserName
#Column(name = "INSTITUTION_USER_NAME")
private String institutionUserName;
#Column(name = "INSTITUTION_USER_ROLE")
private String userRole;
}
Update to the Entity Class InsstitutionUserCredentialMaster :-
#Entity(name = "INSTITUTION_USER_CREDENTIAL_MASTER")
public class InstitutionUserCredentialMaster {
#EmbeddedId
private InstituteUserCredentialMasterPrimaryKey instituteUserCredentialMasterPrimaryKey;
#Column(name = "INSTITUTION_USER_STATUS")
private String userStatus;
#Column(name = "INSTITUTION_NAME")
private String institutionName;
#Column(name = "LAST_UPDT_ID")
private String lastUpdateId;
#Column(name = "LAST_UPDT_TS")
private String lastUpdateTimestamp;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="institutionUserId", referencedColumnName = "INSTITUTION_USER_ID"),
#JoinColumn(name="institutionUserName",referencedColumnName = "INSTITUTION_USER_NAME")
})
private InstitutionUserCredential institutionUserCredential;
}
This time i am getting an error like
Invocation of init method failed; nested exception is org.hibernate.DuplicateMappingException: Table [institution_user_credential_master] contains physical column name [institution_user_id] referred to by multiple physical column names: [institutionUserId], [INSTITUTION_USER_ID]
I think that the problem is that you are not referencing the other part of the EmbeddedId in the JoinColumns annotation. You have defined that also the institutionUserName is part of the primary key, so you should mention it as well in the definition of the foreign key in entity InstitutionUserCredentialMaster.

jpa / hibernate how to map element collection by foreign key with annotations

Given these two tables:
CREATE TABLE `soc` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32),
PRIMARY KEY (`id`));
CREATE TABLE `soc_attitude` (
`soc_id` INT NOT NULL,
`target_soc_id` INT NOT NULL,
`attitude` INT,
PRIMARY KEY (`soc_id`,`target_soc_id`));
In the Soc class, I want to get all rows matching this.soc_id from the soc_attitude table using a field like this:
private Map<Integer,Integer> attitudes;
Where the key of the map is target_soc_id and the value is attitude.
I got as far as this:
#Entity
#Table(name = "soc")
public class Soc {
#Id
#Column( name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name="name")
private String name;
#ElementCollection
#CollectionTable(name="soc_attitude",joinColumns=#JoinColumn(name="soc_id"))
#Column(name="attitude")
private Map<Integer,Integer> attitudes;
But I think this will make soc_id the key and attitude the value.
What annotations do I use? (using Hibernate 4.3.11.Final)
Use #MapKeyColumn
Try this:
#ElementCollection
#CollectionTable(name="soc_attitude",joinColumns=#JoinColumn(name="soc_id"))
#Column(name="attitude")
#MapKeyColumn(name="target_soc_id")
private Map<Integer,Integer> attitudes;

Trouble with a mapped class (OneToMany) containing OneToOne mappings

I have been trying to map some "OneToOne" relationships between two users via an intermediate class called Guardian. When i try to retrieve a user (and his guardians) i get an internal server error in return from Glassfish (Open edition v4.0). There is however no stack trace of any kind or any error displayed in the logs. I suspect that the issue is my mapping within the JPA classes.
Starting the server i get two warnings related to the Guardian class which I don't really understand:
WARNING: The reference column name [GUARDIAN] mapped on the element [method getGuardianUserBean] does not correspond to a valid id or basic field/column on the mapping reference. Will use referenced column name as provided.
WARNING: The reference column name [OWNER] mapped on the element [method getOwnerUserBean] does not correspond to a valid id or basic field/column on the mapping reference. Will use referenced column name as provided.
SQL create statements:
create table HOMEFREE."user" (
userid integer GENERATED ALWAYS AS IDENTITY,
name varchar(255) not null,
displayname varchar(255) unique not null,
password varchar(255) not null,
tlf integer,
facebookID varchar(255),
googleid varchar(255),
authtoken varchar(255),
email varchar(255) unique not null,
primary key(userid)
);
create table HOMEFREE."guardian" (
guardianId integer GENERATED ALWAYS AS IDENTITY,
owner integer not null,
guardian integer not null,
confirmed boolean not null,
primary key(guardianId),
foreign key(owner) references homeFree."user"(userid),
foreign key(guardian) references homeFree."user"(userid)
);
Relevant fields/annotations in entity classes:
#Entity
#Table(name = "\"user\"", schema = "HOMEFREE")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
#OneToMany(mappedBy = "ownerUserBean", fetch = FetchType.EAGER)
private List<Guardian> guardians;
}
#Entity
#Table(name="\"guardian\"", schema="HOMEFREE")
public class Guardian implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int guardianId;
#OneToOne
#PrimaryKeyJoinColumn(name="OWNER", referencedColumnName="USERID")
private User ownerUserBean;
#OneToOne
#PrimaryKeyJoinColumn(name="GUARDIAN", referencedColumnName="USERID")
private User guardianUserBean;
private boolean confirmed;
}
Try using #JoinColumn instead of #PrimaryKeyJoinColumn.
#OneToOne
#JoinColumn(name="OWNER", referencedColumnName="USERID")
private User ownerUserBean;
#OneToOne
#JoinColumn(name="GUARDIAN", referencedColumnName="USERID")
private User guardianUserBean;
According to spec the latter should be used to join the primary table of an entity subclass in the JOINED mapping strategy to the primary table of its superclass (exact definition available here)

Categories