update all fields of an entity in jpa - java

I have tow entity User and Project that they have "one to many" relationship and I want to find the User then find the specific Project that belong to User and then update it, but I can't.
framework Struts2 + Hibernate .
#Entity (name = "User")
#Table (name = "users")
public class User implements Serializable{
#Id
#Column (name = "user_id", columnDefinition = "number")
#SequenceGenerator(name = "seq", sequenceName = "gen")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
private int id;
#Basic
#Column(name = "user_name", columnDefinition = "nvarchar2(20)")
private String userName;
#Basic
#Column(name = "password", columnDefinition ="nvarchar2(20)")
private String password;
#Basic
#Column(name = "create_date",columnDefinition = "date")
private Date creation_date;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private List<Project> projectses;
public List<Project> getProjectses() {
return projectses;
}
public void setProjectses(List<Project> projectses) {
this.projectses = projectses;
}
and Project entity
#Entity(name = "Project")
#Table(name = "project")
public class Project implements Serializable {
#Id
#Column(name = "project_id" , columnDefinition = "number")
#SequenceGenerator(name = "projectSeq", sequenceName = "projectGen")
#GeneratedValue(strategy = GenerationType.AUTO,generator = "projectSeq")
private int projectId;
#Basic
#Column(name = "project_name" , columnDefinition = "nvarchar2(20)")
private String projectName;
#Basic
#Column(name = "project_description" , columnDefinition = nvarchar2(20)")
private String projectDescription;
#Basic
#Column(name = "start_date",columnDefinition = "date")
private Date startDate;
#Basic
#Column(name = "due_date",columnDefinition = "date")
private Date dueDate;
#Basic
#Column(name = "project_status",columnDefinition = "nvarchar2(20)")
private String projectStatus;
#Basic
#Column(name = "project_amount",columnDefinition = "number(8)")
private int projectAmount;

Three corrections come in mind, that may make your code behave well:
Use EntityManager#find() instead of HQL to lookup entity by id;
Use only one of #Basic or #Column (I'd prefer #Column), there is no need to use both for a single element;
If error is "value is too long for column", maybe it is time to check if some of Project elements are longer than 20 chars defined in columnDefinition?
Check length of string elements in Project entities, and if there are some longer than 20 characters, say, 500, modify columnDefinition for those elements, e. g.:
#Column(name = "project_description", columnDefinition = "nvarchar2(500)")
private String projectDescription;
I also suggest to drop tables after such modifications (to allow JPA create new according to new definitions) or manually modify their definitions in DB.

User u = (User)entityManager.createQuery(SELECT u FROM User u JOIN FETCH u.Project where u.id = :id).setParameter("id",your_userId).uniqueResult();
Get The user object , you will get it with the set of projects associated with that user
update the data you want : -
List<Project> userProjects = u.getProjectses();
for(int i = 0 ; i < userProjects.size() ; i++){
Project p = userProjects.get(i);
entityManager.getTransaction().begin();
p.setProjectName("test");
entityManager.merge(p);
entityManager.getTransaction().commit();
}

Related

I need to get all distinct columns from the same table by the same code utilizing Hibernate

I have a table with n x n relationship. That means i have a code that is repeated with only a "brand" column being different between them. The code is not the ID.
I need to have one distinct class that contains all repeatable values and with a list that has all the unique brand column values.I cannot show most of the code samples because of my company security policies. But the entity below is a mock of what i'm seeking.
`
#Entity
#Table(name = "Table")
public class Teste {
#Column(name = "CODE", insertable = false, updatable = false)
private String code;
#Column(name = "NAME")
private String name;
#Column(name = "BRAND")
private String brand;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "BRAND", joinColumns = { #JoinColumn(name = "CODE"), #JoinColumn(name = "BRAND")})
private Set<Model> brands = new HashSet<>();
#Column(name = "UPDATE_DATE")
private Date update_date;
#Column(name = "EDITOR")
private String editor;
#Id
#Column(name = "ID")
private int id;
}
`

Spring boot JPA related entity clarification

I have an entity like Process, which will be created by , updated by one user. When I try to apply the filter. I have created the foreign key relationship in the database. Now, when I use the JPA Specification to apply dynamic filter, I am getting exception as
No property CREATED found for type Process!
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
}
Hence, I Added the entity relationship mapping in the process entity as given below,
Now, I am getting below error. I am new to JPA and hibernate, the relation mapping is very confusing, kindly help.
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
//newly added below properties so that there will be no error when fetching data
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails CREATED;
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails UPDATED;
}
Now, I am getting the below error
Referenced property not a (One|Many)ToOne: com.app.users.details.domain.UserDetails.id in mappedBy of com.app.scenarios.domain.Process.CREATED
Kindly let me know what i am doing wrong. I have a process which can be created by a user and can be updated by a user. In DB, I am having a foreign key relationship for process and userdetails entity.
EDIT
Code to get the filtered data from DB using JPA Specification
Page<process> result = this.processDao.findAll(getprocessGridData(processSearchCondition.getprocessName()), pageRequest);
private static Specification<process> getprocessGridData(String processName) {
return (Specification<process>) (root, query, criteriaBuilder) -> (
criteriaBuilder.like(root.get("name"), processName)
);
}
I guess what you actually want is this:
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name;
#OneToOne(fetch = FetchType.LAZY)
#jOINColumn(name = "CREATED_BY", updatable = false)
private UserDetails createdBy;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "UPDATED_BY", nullable = true)
private UserDetails updatedBy;
}

Entity fetched using findById has all fields set to NULL

Entity fetched using Hibernate has all fields set to NULL. How can I avoid this?
This is my Jpa Repository.
#Repository
public interface PolicyRepository extends JpaRepository<Entity, Long>{
Entity findByEntSeqNo(#Param("entSeqNo") long entSeqNo);
}
When debugged I can see that fetched data are inside a field name $$_hibernate_interceptor
This is my entity class
#Entity
#Table(name = "ENTITY_TABLE")
#Lazy(value = false)
public class Entity extends AuditModel {
#Id
#Column(name = "ENT_SEQ_NO")
#GeneratedValue(generator="entitySeq")
#SequenceGenerator(name="entitySeq",sequenceName="\"ENT_SEQ_NO_seq\"", allocationSize=1)
private long entSeqNo;
#Column(name = "ENT_CUSTOMER_CODE")
#NotEmpty(message = "Customer Code is Required.")
private String entCustomerCode;
#Column(name = "ENT_CLAS_CODE")
#NotEmpty(message = "Class Code is Required.")
private String polcClasCode;
#Column(name = "ENT_PROD_CODE")
#NotEmpty(message = "Product Code is Required.")
private String entProdCode;
#Column(name = "ENT_BRANCH_CODE")
#NotEmpty(message = "Branch Code is Required.")
private String entBranchCode;
#Column(name = "ENT_YYY_NO")
#NotEmpty(message = "Yyy Number is Required.")
private String entYyylNo;
#Column(name = "ENT_XX_NO")
private String entXxNo;
#Column(name = "ENT_XXX_NO")
private String entXxxNo;
#Column(name = "ENT_COMMENCEMENT_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entCommencementDate;
#Version
#NotNull(message = "Version is Required.")
#Column(name = "VERSION")
private int version;
#Column(name = "ENT_EXPIRY_DATE")
#NotNull(message = "Entity Expiry Date is Required.")
#Temporal(TemporalType.TIMESTAMP)
private Date entExpiryDate;
#Column(name = "ENT_DELIVERY_MODE")
private String entDeliveryMode;
#Column(name = "ENT_COLLECTED_BY")
private String entCollectedBy;
#Column(name = "ENT_COLLECTED_USER_NIC")
private String entCollectedUserNic;
#Column(name = "ENT_COLLECTED_USER_MOBILE")
private String entCollectedUserMobile;
#Column(name = "ENT_COLLECTED_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entCollectedDate;
#Column(name = "ENT_POSTED_DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date entPostedDate;
#Column(name = "ENT_POSTED_REF_NO")
private String entPostedRefNo;
#Column(name = "ENT_LANG_CODE")
private String entLangCode;
#Column(name = "ENT_PP1_ID", insertable = false, updatable = false)
private Long entPp1Id;
#Column(name = "ENT_STATUS")
private Short entStatus;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENT_PP1_ID", referencedColumnName = "ID")
private Pp1 entPp1;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENT_EPP1_ID", referencedColumnName = "ID")
private Epp1 entEpp1;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx")
private Collection<TaskLog> taskLogColletion;
}
I'm asking this here since I couldn't find the exact cause for this behavior. All the Jpa operations are working fine and this happens only when I try to pick the details from the database. I also tried getOne method and the same problem occurs.
You do not need the method : Entity findByEntSeqNo(#Param("entSeqNo") long entSeqNo); in your jpa interface because entSeqNo is an id of your entity.
So whene you want to get one Entity by id you can just call policyRepository.getOne(the value of entSeqNo) provided by JpaRepository
Or you can use policyRepository.findById(the value of entSeqNo) provided by CrudRepository whitch is basically a superinterface of JpaRepository
Ps: Do no overwrite these methods in you interface.

Hibernate unexpected deletes when finding entities

We have a Java ee application running on JBoss 6.4 GA using JPA and Hibernate with the following entities:
#Entity
#SequenceGenerator(name = "sequence", sequenceName="SEQ_CAMPAIGNS_ID",allocationSize = 1)
#Table(name = "CAMPAIGN")
public class CampaignEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "IS_ACTIVE", nullable = false)
private boolean active;
#Column(name = "START_DATE", nullable = false)
private Date startDate;
#Column(name = "END_DATE", nullable = false)
private Date endDate;
#Column(name = "LEGAL_ENTITY_ID", nullable = false)
private Integer legalEntityId;
#Column(name = "DEPARTMENT", nullable = false)
#Enumerated(value = EnumType.STRING)
private Department department;
#Column(name = "CATEGORY", nullable = false)
#Enumerated(value = EnumType.STRING)
private Category category;
#Embedded
CampaignConditionsEntity campaignConditions;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "campaign", orphanRemoval = true)
#OrderBy
private List<CodeEntity> campaignCodes;
public CampaignEntity() {
}
And the following CampaignConditionsEntity:
#Embeddable
public class CampaignConditionsEntity implements Serializable {
private static final String CAMPAIGN_ID = "CAMPAIGN_ID";
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CAMPAIGN_COND_TRIP_TYPE", joinColumns = #JoinColumn(name = CAMPAIGN_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
And the following CodeEntity:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#SequenceGenerator(name = "sequence", sequenceName = "SEQ_CODES_ID", allocationSize = 1)
public abstract class CodeEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
#Column(name = "ID", nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CAMPAIGN_ID")
private CampaignEntity campaign;
#OneToOne(mappedBy = "code", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, orphanRemoval = true)
private DiscountEntity discount;
#Column(name = "MAX_USAGES", nullable = false)
private Integer maxUsages;
#Column(name = "UNLIMITED_USAGES", nullable = false)
private boolean unlimitedUsages;
#Column(name = "NEGATIVE_SH", nullable = false)
private boolean negativeSH;
#Column(name = "UNIQUE_BUYER", nullable = false)
private boolean uniqueBuyer;
#Column(name = "START_DATE")
private Date startDate;
#Column(name = "END_DATE")
private Date endDate;
#Embedded
private CodeConditionsEntity codeConditions;
public CodeEntity() {
}
This is the CodeConditionsEntity:
#Embeddable
public class CodeConditionsEntity implements Serializable {
private static final String CODE_ID = "CODE_ID";
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CODE_COND_TRIP_TYPE", joinColumns = #JoinColumn(name = CODE_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CODE_COND_CARRIERS", joinColumns = #JoinColumn(name = CODE_ID))
private Set<CarrierConditionEntity> carrierConditions;
This is the CarrierConditionEntity:
#Embeddable
public class CarrierConditionEntity implements Serializable {
#Column(name = "CARRIER", nullable = false, length = 3)
private String carrierCode;
#Column(name = "IS_INCLUDED", nullable = false)
private boolean included;
The problem is that in the logs we are finding unexpected deletes when the only operation that we are doing are finds of particular campaign entities.
In the production logs we find the following deletes
Hibernate: delete from CODE_COND_CARRIERS where CODE_ID=? and CARRIER=? and IS_INCLUDED=?
do you have any suggestion?
thanks
I have some suggestions :)
Be aware of what is a Persistence Context (EntityManager instance in JPA terminology / Session in Hibernate one), the entity lifecycle and transaction scope (unit of work)
Do not mutate entity state if you don't expect the changes to be reflected in database, or at least detach the entity before mutating it.
Mark your transaction as "readOnly" if you only fetch data in the related unit of work. (beware that if you have many "Transactional" methods joining the same physical transaction, the flag is set by the surrounding one and cannot be overridden by inner logical transactions). That way the EntityManager won't be flushed at the end of the transaction and pending changes won't be persisted to the database.
You can track the method triggering the unexpected deletion using an EntityListener on the related entity and printing the current strackTrace (new Throwable().printStackTrace()/ log(new Throwable()) in the PreRemove method
I found where was the problem:
The problem was that the Entities didn't have the equals() and the hashcode() implemented. Also there were entities that have a #PostLoad that modified the entity after loading it from database. Then in this situation Hibernate though that there was a change in those entities that didn't have the equals and the hashcode, and then it delete all of them and inserted again in the database (to have the same entities before the query)
Adding the equals and hashcode methods and deleting postload removed the unexpected deletes and inserts from the logs.
regards

Hibernate List Mapping Annotation

Well i have this problem
These are my tables
this is my code for "Compra"
#Entity
#Table(name = "compra")
public class Compra implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "codigo", unique = true, nullable = false)
private int codigo;
#ManyToOne
#JoinColumn(name = "codProveedor", nullable = false)
private Proveedor proveedor;
#Column(name = "tipoComprobante", nullable = false)
private String tipoComprobante;
#Temporal(TemporalType.DATE)
#Column(name = "fechaFactura", nullable = false)
private Date fechaFactura;
#Temporal(TemporalType.DATE)
#Column(name = "fechaLlegada", nullable = false)
private Date fechaLlegada;
#Column(name = "serie", nullable = false)
private String serie;
#Column(name = "numero", nullable = false)
private int numero;
#Column(name = "importe", nullable = false)
private double importe;
#Column(name = "vigencia", nullable = false)
private boolean vigencia = true;
#ElementCollection
private List<DetalleCompra> lstDetalle = new ArrayList<DetalleCompra>();
// getters and setters ...
And this is my code for "DetalleCompra"
#Entity
#Table(name = "detalleCompra")
public class DetalleCompra implements Serializable {
#Id
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign", parameters = #Parameter(name = "property", value = "compra"))
#Column(name = "codCompra", nullable = false)
private int codCompra;
#ManyToOne
#JoinColumn(name = "codPresentacion", nullable = false)
private Presentacion presentacion;
#Column(name = "imei", nullable = false)
private String imei;
#Column(name = "simcard", nullable = false)
private String simcard;
getters and setters ...
Well everything looks fine, but when i want to save i have this problem
org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: DetalleCompra
well it is clear because when i want to save Compra and DetalleCompra, the second table expect the fk value
public void registrar(Compra compra) {
try {
session = HibernateUtil.getSessionFactory().openSession();
trans = session.beginTransaction();
session.save(compra);
trans.commit();
} catch (Exception e) {
trans.rollback();
throw e;
} finally {
session.close();
}
}
Well the pk of table "compra" is generated well but for the other table does not recognized this value autogenerated, why?, how can i solve that?
#ElementCollection
Defines a collection of instances of a basic type or embeddable class.
Must be specified if the collection is to be mapped by means of a
collection table.
You use wrong annotation to represent relation. There is one to many relation between Compra and DetalleCompra.
You should change #ElementCollection annotation to #OneToMany. Do not forget to specify join columns #JoinColumn(name="codCompra"). I assume that Presentacion is properly mapped.
See also
Unidirectional Mapping vs. Bidirectional Mapping
mappedBy attribute
#OneToMany annotation
#ElementCollection annotation

Categories