why i get null at relationship field? - java

Why if i run this code:
Student st = new Student();
st.setFirstName("First");
st.setLastName("Last");
st.setIndexNr("11");
st.setStudentPK(new StudentPK(0, user.getIdUser()));
studentFacade.create(st);
Mail m = new Mail();
m.setContent("con");
m.setRecipient("rec");
m.setIdMail(0);
mailFacade.create(m);
List<Mail> l = new ArrayList<Mail>();
l.add(m);
st.setMailList(l);
studentFacade.edit(st); // st have mailList property set to l
stud=studentFacade.findByIndex("11"); //after edit and get student he has mailList equal null
Why after persist and edit object i get null at property for OneToMany relationship?
In database MySql i have STUDENT table and MAIL table:
CREATE TABLE IF NOT EXISTS `STUDENT` (
`id_student` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
`first_name` VARCHAR(65) NULL ,
`last_name` VARCHAR(65) NULL ,
`index_nr` VARCHAR(45) NULL
)
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `MAIL` (
`id_mail` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`recipient` TEXT NULL ,
`content` TEXT NULL ,
`sender_student` MEDIUMINT UNSIGNED NULL ,
PRIMARY KEY (`id_mail`) ,
INDEX `fk_STUDENT_id_idx` (`sender_student` ASC) ,
CONSTRAINT `fk_STUDENT`
FOREIGN KEY (`sender_student` )
REFERENCES `jkitaj`.`STUDENT` (`id_student` )
ON DELETE CASCADE
ON UPDATE CASCADE
)
ENGINE = InnoDB
From database i generate entity in netbeans:
#Entity
#Table(name = "STUDENT")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected StudentPK studentPK;
#Size(max = 65)
#Column(name = "first_name")
private String firstName;
#Size(max = 65)
#Column(name = "last_name")
private String lastName;
#Size(max = 45)
#Column(name = "index_nr")
private String indexNr;
#OneToMany(mappedBy = "senderStudent",fetch=FetchType.EAGER)
private List<Mail> mailList;
//getters, setters ...
}
public class Mail implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Basic(optional = false)
#Column(name = " id_mail")
private Integer idMail;
#Lob
#Size(max = 65535)
#Column(name = "recipient")
private String recipient;
#Lob
#Size(max = 65535)
#Column(name = "content")
private String content;
#JoinColumn(name = "sender_student", referencedColumnName = "id_student")
#ManyToOne
private Student senderStudent;
//getters, setters...
}
EDIT:
I think i forget about fetch in #OneToMany annotation of Student entity. But when i set in to fetch=FetchType.LAZY i again get null after edit and and get edited object from database. When set fetch=FetchType.EAGER mailList field isn't null. Why ?

Problem is at OpenJPA, when i use fetch=FetchType.LAZY at some property of entity. The problem was with life cycle of enties. All enties must be re-attached to the persistence context.
Same problem is here: OpenJPA - lazy fetching does not work and here: What's the lazy strategy and how does it work?

You have a unique combination of too much information with too little.
If you are actually running that code, then package it up as a complete, runnable example -- yes, it won't run on another machine unless that machine also has a database setup, but it will tell us everything you're doing instead of just the part that you think is important.
Give us the complete error message, don't tell us what it is.
Two important things to remember about posting a question on a site like this: you don't know what's wrong, so you need to give us complete raw data, not half-analysis. And it is generally a waste of time for us to just guess at things.

Related

Logical delete and create with Hibernate

#Entity
#Table(name = "Country")
#SQLDelete(sql = "UPDATE Country SET date_deleted=NOW() WHERE code = ?")
#Where(clause = "date_deleted is NULL")
public class Country {
#Id
#Column(name = "code", nullable = false)
private String code;
#Column(name = "description")
private String description;
#Column(name = "date_deleted")
private Date date_deleted;
....
}
When I logic delete an Entity in the database with the code 'U1' and after, I created a new Entity with the same code 'Ü1', occurs an exception "duplicate entry". Has Hibernate an annotation to solve this problem?
edit:
The Error when I insert a new entity with the same code is this:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates
unique constraint "country_pkey" Detail: Key (code)=(AA) already
exists.
The table is:
CREATE TABLE public.country(
code bpchar(2) NOT NULL,
description bpchar(50) NULL,
date_deleted timestamp NULL,
CONSTRAINT country_pkey PRIMARY KEY (code),
CONSTRAINT constraint_country UNIQUE (date_deleted, code) -- I add this constraint
);
Since you manage the code column and you can have multiple entries with the same code, one solution would be to have an id column that is autogenerated.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
This will enable you to delete an object with the code 'U1' and add another one with the same code.
You can check this great tutorial: https://vladmihalcea.com/the-best-way-to-soft-delete-with-hibernate/

I have an error when accessing a field with JPA. How do I solve this?

When trying to insert values into my table, i get this error
org.hibernate.property.access.spi.PropertyAccessException: Error accessing
field [private int com.app.demo.model.Customer.id] by reflection for
persistent property [com.app.demo.model.Customer#id] :
com.app.demo.model.Customer#6d1c6e1e
javax.persistence.PersistenceException:
org.hibernate.property.access.spi.PropertyAccessException: Error accessing
field [private int com.app.demo.model.Customer.id] by reflection for
persistent property [com.app.demo.model.Customer#id] : com.app.demo.model.Customer#6d1c6e1e
This is my customer table. I am using MySql Workbench, and I am trying to insert my values into here.
And i am using using this class to insert values into the table
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue
#Column(name = "customer_id", unique = true, nullable = false)
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="street_address")
private String address;
#Column(name="city")
private String city;
#Column(name="state")
private String state;
#Column(name="zip_code")
private String zipcode;
#Column(name="email")
private String email;
#Column(name="paypal_email")
private String paypalEmail;
// getters and setters
And this is how I am inserting values into my table
// Set customer values
Customer valuedCustomer = new Customer();
valuedCustomer.setFirstName(firstName);
valuedCustomer.setLastName(lastName);
valuedCustomer.setAddress(address);
valuedCustomer.setCity(city);
valuedCustomer.setState(state);
valuedCustomer.setZipcode(zip);
valuedCustomer.setEmail(email);
// insert customer info into the customer table
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(valuedCustomer);
em.getTransaction().commit();
EDIT:
My customer table
My user table (this table i did the unit test on)
try using AUTO or IDENTITY policy.
like:
#GeneratedValue(strategy = GenerationType.IDENTITY)
Here is the ID field definition in your entity class
#Id
#GeneratedValue
#Column(name = "customer_id", unique = true, nullable = false)
private int id;
Here ID field is unique and not null. So you must have to provide the data on ID field during insertion.
First of all, using annotations as our configure method is just a convenient method instead of coping the endless XML configuration file.
The #Idannotation is inherited from javax.persistence.Id, indicating the member field below is the primary key of current entity. Hence your Hibernate and spring framework as well as you can do some reflect works based on this annotation. for details please check javadoc for Id
The #GeneratedValue annotation is to configure the way of increment of the specified column(field).
For example when using Mysql, you may specify auto_increment in the definition of table to make it self-incremental, and then use
#GeneratedValue(strategy = GenerationType.IDENTITY)

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.

Representing #EmbeddedId as SQL for H2 database

I am currently working on a Java project with Hibernate entities (more below). In order to test my data access object layers, I am using H2 database to populate an in-memory database and throwing queries at it. Until this point, everything is fine.
However, the problem comes when simulating the #EmbeddedId annotation.
#Entity
#Table(name = "BSCOBJ")
public class BasicObject extends AbstractDomainObject {
#EmbeddedId // This annotation here
private RestrainPK restrain;
#Embeddable
public static class RestrainPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "CODI", nullable = false)
private String coDi;
#Column(name = "COGA", nullable = false)
private String coGa;
#Column(name = "TYOR", nullable = false)
private String tyOr;
public RestrainPK() {
}
... // Getters and setters
}
}
"Simply" creating the table BSCOBJ and populating it gives no value when fetching data (of course, I checked that the request would give result "normally"). How do I represent this nested class in a SQL table creation / value insertion request ? Is that even possible ?
Thanks in advance,
EDIT
As requested, here is some samples about the SQL / Hibernate ran.
Creation request:
CREATE TABLE BSCOBJ (CODI VARCHAR(5) NOT NULL, COGA VARCHAR(5) NOT NULL, TYOR VARCHAR(5) NOT NULL);
Insertion request:
INSERT INTO BSCOBJ (CODI, COGA, TYOR) VALUES
('HELLO', 'MAT', 'REF'),
('BONJ', 'SOME', 'DAIL'),
('SOPA', 'KDA', 'RATIO');
Request given by Hibernate when trying to run the test code:
select r.restrain.tyOr from mypackage.BasicObject r where r.restrain.coDi = :coDi and r.restrain.coGa = :coGa
With the following values:
coDi = "BONJ";
coGa = "SOME";
Throws a NoResultException. I am expecting DAIL, from the second line of the INSERT request.
I have used #EmbeddedId only one time, but I think that you need #AttributeOverrides under your #EmbeddedId
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "idpk", column = #Column(name="IDPK", nullable = false),
#AttributeOverride(name = "code", column = #Column(name="CODE")
})
and remove your #Column annotations from FormulePK

One-to-One mappings of basic type, into a single class in Hibernate

So the situation is as follows: there is an entity which needs to be connected with a dictionary. Imagine a following structure
create table Address (
addressId bigint not null,
addressLine1 varchar(255),
city varchar(255),
country varchar(255),
state varchar(255),
zipCode varchar(255),
primary key (addressId)
)
create table STATES_DICT (
state_code varchar(255),
state_fullname varchar(255),
primary key (state_code)
)
I want to map both ADDRESS and STATE_DICTIONARY into a single entity.
#Entity
#Table(name = "ADDRESS")
public class Address implements Serializable {
#Id
#Column(name = "ADDRESSID")
private int addressId;
#Column(name = "ADDRESSLINE1")
private String addressLine1;
#Column(name = "STATE")
private String state;
//??? annotations
private String fullStateName;
#Column(name = "ZIPCODE")
private String zipCode;
#Column(name = "CITY")
private String city;
#Column(name = "COUNTRY")
private String country;
//... getters and setters
}
For a pure SQL I'll run
select a.ADDRESSID, a.ADDRESSLINE1, a.CITY, a.ZIPCODE, a.STATE,
d.STATE_FULLNAME, a.COUNTRY
from ADDRESS a, STATES_DICT d where a.STATE = d.STATE_CODE
but I'm having severe problems with mapping it with JPA.
I cannot use #SecondaryTable because the tables are not mapped by primary keys
The best I could get was:
#ElementCollection
#JoinTable(name="STATES_DICT",
joinColumns=#JoinColumn(name="STATE_CODE", referencedColumnName="STATE"))
#Column(name = "STATE_FULLNAME")
private Collection<String> fullStateName;
Downside is - the mapping is always one-to-one and the Collection brings confusion and the relation is more of one-to-one (many-to-one) not one-to-many.
Any ideas? Is there an equivalent of #ElementCollection for one-to-one mappings?
Dropping the #ElementCollection does not help. fullStateName field is expected to be in ADDRESS column - which is not the case.
Some notes:
* I need those two to keep together in a single entity.
* I'm extending existing solution, need to add just this dictionary column
* The entity is processed later on by some other service which runs through primitive types only. I'd rather not change the service, that's why adding a #OneToOne relation is not preferable
Many thanks
I'm extending the question with #SecondaryTable example - which didn't work for me.
#Entity
#Table(name = "ADDRESS")
#SecondaryTable(name="STATES_DICT",
pkJoinColumns=#PrimaryKeyJoinColumn(columnDefinition="STATE_CODE", referencedColumnName="STATE"))
public class Address implements Serializable {
#Id
#Column(name = "ADDRESSID")
private int addressId;
#Column(name = "ADDRESSLINE1")
private String addressLine1;
#Column(name = "STATE")
private String state;
#Column(table="STATES_DICT", name = "STATE_FULLNAME")
private String fullStateName;
#Column(name = "ZIPCODE")
private String zipCode;
#Column(name = "CITY")
private String city;
#Column(name = "COUNTRY")
private String country;
//... getters and setters
}
That caused a nasty exception of:
Caused by: org.hibernate.AnnotationException: SecondaryTable JoinColumn cannot reference a non primary key
For the record - I couldn't find a way to do this (and assumed it's simply not the way it should be done). I've gone with relation annotations (#ManyToOne, #OneToOne) and #JoinColumn - so the proper way. I've adjusted the further processing logic to treat #JoinColumn annotations in the same way it's working with #Column. It worked.
The further processing is a security feature which suppresses values based on user roles and original database column names. That's why it was so important for me to stick with the #Column annotation
Answer from user2601805 is correct using
#PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")
In your case, this should suffice as all you want is a property from STATES_DICT.
I also asked a question relating to JPA that shows an example for using #SecondaryTable and #Embeddable to achieve something similar to #ElementCollection but for #OneToOne
Also see this blog for example http://www.bagdemir.com/2013/03/03/mapping-embeddable-objects-whichve-no-identities-using-multiple-tables-with-jpahibernate/
You should be able to create an #Embeddable State class that maps the relationship, but provide a delegate method to expose the state name as a property. Would this accomplish what you're trying to do?
In #pkJoinColumns you should use:
#PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")
I have same problem and your hint to use #SecondaryTable solved my problem. See Mapping one entity to several tables for more information.

Categories