how to make #id fields editable in forge crud? - jboss

I want to generate a crud for an entity with an editable primary key but forge doesnt generate the #id field this is my entity note that the id field is an string it is not a an auto increment id field.
package com.samples.model;
// Generated 14/01/2013 11:23:23 AM by Hibernate Tools 3.4.0.CR1
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Pais generated by hbm2java
*/
#Entity
#Table(name = "pais", schema = "public")
public class Pais implements java.io.Serializable
{
/**
*
*/
private static final long serialVersionUID = -8369022633869576848L;
private String paisId;
private Date fechaRegistro;
private String descripcion;
private short estatus;
private Set<Estado> estados = new HashSet<Estado>(0);
public Pais()
{
}
public Pais(String paisId, Date fechaRegistro, short estatus)
{
this.paisId = paisId;
this.fechaRegistro = fechaRegistro;
this.estatus = estatus;
}
public Pais(String paisId, Date fechaRegistro, String descripcion, short estatus, Set<Estado> estados)
{
this.paisId = paisId;
this.fechaRegistro = fechaRegistro;
this.descripcion = descripcion;
this.estatus = estatus;
this.estados = estados;
}
#Id
#Column(name = "pais_id", unique = true, nullable = false, length = 5)
public String getPaisId()
{
return this.paisId;
}
public void setPaisId(String paisId)
{
this.paisId = paisId;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "fecha_registro", nullable = false, length = 29)
public Date getFechaRegistro()
{
return this.fechaRegistro;
}
public void setFechaRegistro(Date fechaRegistro)
{
this.fechaRegistro = fechaRegistro;
}
#Column(name = "descripcion", length = 30)
public String getDescripcion()
{
return this.descripcion;
}
public void setDescripcion(String descripcion)
{
this.descripcion = descripcion;
}
#Column(name = "estatus", nullable = false)
public short getEstatus()
{
return this.estatus;
}
public void setEstatus(short estatus)
{
this.estatus = estatus;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pais")
public Set<Estado> getEstados()
{
return this.estados;
}
public void setEstados(Set<Estado> estados)
{
this.estados = estados;
}
}

JBoss Forge uses Metawidget for its UI generation. So to accomplish this you must modify Forge's metawidget.xml configuration file.
Forge actually has 3 Metawidget configuration files: metawidget-entity.xml for viewing/editing screens, metawidget-search.xml for search filters, and metawidget-qbe.xml for generating Java code.
For your purposes, you need to modify metawidget-entity.xml. Specifically you must find the JpaInspector entry...
<jpaInspector xmlns="java:org.metawidget.inspector.jpa" config="JpaInspectorConfig">
...and add a child node...
<hideIds><boolean>false</boolean></hideIds>
That bit should be straightforward. However actually getting your modified metawidget-entity.xml back into Forge is clumsy. At the moment the easiest way is probably to unzip and modify the forge-scaffold-faces.jar itself. Hopefully this will be made cleaner in a future Forge release.

Related

JPA won't save an entity correctly unless the references to other entities are set

If I save this entity using JPA repository with a new defaultAssetId, it will only update the defaultAsssetId to the new value if I set defaultAsset as well. I want to be able to save without setting defaultAsset.
Same problem applies to taskType and assetRole.
package au.com.polonious.conf.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
#Entity
public class TaskTypeAssetRole implements Serializable {
#GenericGenerator(name="tasktypeassetroleidseq",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "tasktypeassetroleidseq"),
#Parameter(name = "initial_value", value = "1"),
#Parameter(name = "increment_size", value = "1")
})
#Id
#GeneratedValue(generator = "tasktypeassetroleidseq")
private Long id;
#Column(insertable = false, updatable=false)
private Long taskTypeId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="tasktypeid")
private TaskType taskType;
#Column(insertable = false, updatable=false)
private Long assetRoleId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="assetRoleId")
private Role assetRole;
#Column(insertable = false, updatable=false)
private Long defaultAssetId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="defaultassetid")
private Asset defaultAsset;
private Date startDate;
private Date endDate;
private String notes;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getTaskTypeId() {
return taskTypeId;
}
public void setTaskTypeId(Long taskTypeId) {
this.taskTypeId = taskTypeId;
}
public TaskType getTaskType() {
return taskType;
}
public void setTaskType(TaskType taskType) {
this.taskType = taskType;
}
public Long getAssetRoleId() {
return assetRoleId;
}
public void setAssetRoleId(Long assetRoleId) {
this.assetRoleId = assetRoleId;
}
public Role getAssetRole() {
return assetRole;
}
public void setAssetRole(Role assetRole) {
this.assetRole = assetRole;
}
public Long getDefaultAssetId() {
return defaultAssetId;
}
public void setDefaultAssetId(Long defaultAssetId) {
this.defaultAssetId = defaultAssetId;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
I tried saving a taskTypeAssetRole with a new defaultAssedId without setting defaultAsset and I expected the defaultAssedId for that entry in the database to be updated.
What ended up happening was defaultAssetId didn't change although everything else in the entry did update successfully and there were no errors.
Your mapping is inherently broken. The column defaultassetiId is mapped to two different values: the field defaultAssetId and to the id of defaultAsset.
You should remove the defaultAssetId because this construct might break on any update of your JPA provider.
You can use references instead of full entities to set the reference values without loading entities from the database. See https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html#getReferenceById-ID-
If you don't follow this advice you should remove updatable=false if you want to update a field.

When using discriminator value for single table strategy, the first inserted entity's discriminator value is null but the value is there in database

When using discriminator value for inheritance/single table strategy, the first inserted entity's discriminator value is null but the value is there in the database.
I have to restart the server so that the query result containes the discriminator value:
package entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.STRING)
#DiscriminatorValue("Null")
#Table(name="ALLUSER")
#NamedQueries({
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"),
#NamedQuery(name = "User.findByAccount", query = "SELECT u FROM User u WHERE u.account = :account")
})
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String account;
private String password;
private String userType;
public User() {
super();
}
public User(String account, String password) {
super();
this.account = account;
this.password = password;
}
#Id
#Column(name = "account")
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "user_type", insertable = false, updatable = false, nullable = false)
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
#Override
public String toString() {
return account;
}
}
#Entity
#DiscriminatorValue("Normal")
#NamedQueries({
#NamedQuery(name = "NormalUser.findAll", query = "SELECT u FROM NormalUser u")
})
public class NormalUser extends User implements Serializable{
/**
*
*/
//private String account;
private static final long serialVersionUID = 1L;
private LinkedHashSet<Customer> customers;
public NormalUser() {
super();
}
#OneToMany(fetch=FetchType.EAGER, mappedBy="normalUser", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) //eager can be optimized when deleting a normal user
public LinkedHashSet<Customer> getCustomers() {
return customers;
}
public void setCustomers(LinkedHashSet<Customer> customers) {
this.customers = customers;
}
// #Column(name = "account")
// //have to override in order to get account to use
// public String getAccount() {
// return account;
// }
//
// public void setAccount(String account) {
// this.account = account;
// }
}
If I just add a new normal user(child entity), then query this user whose user type will be null:
I use eclipse-link as the JPA implementation and Java EE three-tiered web architecture.
I know this definitely has something to do with the working of entity manager and persistence but I don't know the details. I also don't know how to resolve it. Any suggestion is welcome!
You are not setting the 'type' field within your entities, and JPA doesn't set it for you - not in the java object anyway. If it isn't set when you persist an entity, it will remain unset for as long as that entity is cached (locally or the shared EMF level cache). Restarting the app works because it clears the cache, forcing any fetches of existing entities to load from the database, where the type was set based on the discriminator column value.
You can set the type when creating the class, or force the data to be reloaded from the database by calling em.refresh on the instance. In this case though, it seems strange to even bother mapping the type column as a basic mapping - the getType method should just return the static discriminator value for the class, and you cannot change the type string anyway.

Why does spring jpa ignore javax.persistence.FetchType.LAZY and javax.persistence.NamedEntityGraph?

I have a basic "Department"/"Employee" example.
Full example here (in master branch) : https://github.com/granadacoder/jpa-simple-example-one.git
If you setup 4 environment variables (listed in the README), the code is runnable/debuggable.
For my "findAll()" method, I am trying to only bring back the scalars of the Department entity. (key and name). Aka, I do NOT want any child Employees to be tacked onto the Department .. when I do a findAll().
I have tried using an name EntityGraph, but it is not working (I still get the full object graph)
I am using FetchType.LAZY as well. (which should have been enough IMHO)... And I am not calling (department) .getEmployees at all.
But I took the extra step of defining and using "departmentJustScalarsEntityGraphName".
#EntityGraph("departmentJustScalarsEntityGraphName")
List<Department> findAll();
The above is loading the entire graph (all department scalar AND the employees) and doing it in an N+1 manner. :(
The #EntityGraph should only be loading the key and name for the findAll() method.
If you find the code comment
/* right here, desperately hoping for each Department in the "entities" to NOT have employees hydrated */
you can put the debugger there and see the issue.
Note, that when I do a "find by single" (findById(key) or findDepartmentByDepartmentNameEquals(name))......I DO want the employees. So answers that broad stroke disassociate the Employees are not ideal.
No matter what I've tried, I'm getting the N+1 issue. (The sample seed data has three Departments.)
Hibernate: select department0_.DepartmentKey as departme1_0_, department0_.CreateOffsetDateTime as createof2_0_, department0_.DepartmentName as departme3_0_ from DepartmentTable department0_
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Hibernate: select employees0_.DepartmentForeignKey as departme6_1_0_, employees0_.EmployeeKey as employee1_1_0_, employees0_.EmployeeKey as employee1_1_1_, employees0_.CreateOffsetDateTime as createof2_1_1_, employees0_.FirstName as firstnam3_1_1_, employees0_.LastName as lastname4_1_1_, employees0_.DepartmentForeignKey as departme6_1_1_, employees0_.Ssn as ssn5_1_1_ from EmployeeTable employees0_ where employees0_.DepartmentForeignKey=?
Here are the main code components:
Department.java
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mycompany.organizationdemo.domain.constants.OrmConstants;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
import java.util.LinkedHashSet;
import java.util.Set;
#Entity
#NamedEntityGraphs({
#NamedEntityGraph(name = "departmentJustScalarsEntityGraphName", attributeNodes = {
#NamedAttributeNode("departmentKey"),
#NamedAttributeNode("departmentName")})
})
#Table(name = "DepartmentTable")
public class Department implements Serializable {
#Id
#Column(name = "DepartmentKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long departmentKey;
#Column(name = "DepartmentName", unique = true)
private String departmentName;
#Column(name = "CreateOffsetDateTime", columnDefinition = OrmConstants.OffsetDateTimeColumnDefinition)
private OffsetDateTime createOffsetDateTime;
//region Navigation
#OneToMany(
mappedBy = "parentDepartment",
cascade = CascadeType.REMOVE,
orphanRemoval = true,
fetch = FetchType.LAZY /* Lazy or Eager here */
)
private Set<Employee> employees = new LinkedHashSet<>();
//endregion
public long getDepartmentKey() {
return departmentKey;
}
public void setDepartmentKey(long departmentKey) {
this.departmentKey = departmentKey;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
//region Navigation
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
//endregion
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Department that = (Department) o;
return new org.apache.commons.lang3.builder.EqualsBuilder()
.append(departmentKey, that.departmentKey)
.append(departmentName, that.departmentName)
.isEquals();
}
#Override
public int hashCode() {
return new org.apache.commons.lang3.builder.HashCodeBuilder(17, 37)
.append(departmentKey)
.append(departmentName)
.toHashCode();
}
}
Employee.java
import com.mycompany.organizationdemo.domain.constants.OrmConstants;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
#Entity
#Table(name = "EmployeeTable")
public class Employee implements Serializable {
#Id
#Column(name = "EmployeeKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long employeeKey;
#Column(name = "Ssn")
private String ssn;
#Column(name = "LastName")
private String lastName;
#Column(name = "FirstName")
private String firstName;
#Column(name = "CreateOffsetDateTime", columnDefinition = OrmConstants.OffsetDateTimeColumnDefinition)
private OffsetDateTime createOffsetDateTime;
//region Navigation
#ManyToOne(fetch = FetchType.LAZY, targetEntity = Department.class)//, cascade = CascadeType.REMOVE)
#JoinColumn(name = "DepartmentForeignKey")
private Department parentDepartment;
//endregion
public long getEmployeeKey() {
return employeeKey;
}
public void setEmployeeKey(long departmentKey) {
this.employeeKey = departmentKey;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
//region Navigation
public Department getParentDepartment() {
return parentDepartment;
}
public void setParentDepartment(Department parentDepartment) {
this.parentDepartment = parentDepartment;
}
//endregion
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return new EqualsBuilder()
.append(employeeKey, employee.employeeKey)
.append(ssn, employee.ssn)
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(employeeKey)
.append(ssn)
.toHashCode();
}
}
Spring JPA
import com.mycompany.organizationdemo.domain.entities.Department;
import com.mycompany.organizationdemo.domaindatalayer.interfaces.IDepartmentRepository;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import javax.transaction.Transactional;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public interface DepartmentJpaRepository extends JpaRepository<Department, Long>, IDepartmentRepository {
#EntityGraph("departmentJustScalarsEntityGraphName")
List<Department> findAll();
#Query("SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.departmentName = :departmentName") /* this works because departmentName is a UNIQUE constraint...otherwise it might give back duplicate parents (Departments) */
Optional<Department> findDepartmentByDepartmentNameEquals(#Param("departmentName") String departmentName);
/* note the below, this is "lookup strategy". see https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods */
Collection<Department> findByCreateOffsetDateTimeBefore(OffsetDateTime zdt);
//#Query("SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.departmentKey IN ?1") /* here a Query will bring back repeat parent (Department) rows */
#EntityGraph(attributePaths = {"employees"})
Collection<Department> findDepartmentByDepartmentKeyIn(Set<Long> departmentKeys);
#Modifying
#Transactional
int deleteDepartmentByDepartmentKey(long departmentKey); /* suffers from N+1 problem */
}
and the repository (plain jane) interface
import com.mycompany.organizationdemo.domain.entities.Department;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public interface IDepartmentRepository {
List<Department> findAll();
Optional<Department> findById(long key);
Optional<Department> findDepartmentByDepartmentNameEquals(String departmentName);
Collection<Department> findByCreateOffsetDateTimeBefore(OffsetDateTime zdt);
Collection<Department> findDepartmentByDepartmentKeyIn(Set<Long> departmentKeys);
Department save(Department item);
int deleteDepartmentByDepartmentKey(long departmentKey);
}
I have found this:
Spring Data JPARepository: How to conditionally fetch children entites
and this:
https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm
Spring Boot is fairly new. (from gradle settings in the project)
spring_plugin_version = '2.2.6.RELEASE'
springBootVersion = '2.2.6.RELEASE'
slf4jVersion = "1.7.25"
javaxInjectVersion = "1"
javaxPersistenceApiVersion = "2.2"
junitVersion = "4.12"
mockitoVersion = "3.3.0"
jacksonAnnotationsVersion = "2.11.0"
modelMapperVersion = "2.3.7"
commonsLangVersion = '3.7'
PS
I'm also using the "convert to Dto" trick (as seen here) : https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application but the Department(orm-entity) is already hydrated by that point. :(

Spring JpaRepository save causes 100s of selects to be generated

Im getting very strange error when I call save on a JpaRepository.
The code seems trivial so i can only think its something to do with configuration.
Basically I call a findBy method on the repository, this returns a list of dao objects exactly as expected, I go through this list setting a timestamp then calling save() on each dao, as soon as the first save is called the log is filled with hundreds of identical select statements, selecting on the dao I'm just trying to save until eventually there is a stack overflow.
What could cause this ???
(note originally I called saveAll() on the list of dao objects - this, unsurprisingly has the same error )
public void triggerDeletion() {
ZonedDateTime expiryDate = ZonedDateTime.now().minus(daysAfterExpiry);
// Get list of conversations to delete
List<ConversationDao> conversationDaoList = conversationDatabaseService.retrieveExpiredConversations(expiryDate);
// Mark each conversation as deleted by setting its deletion timestamp to now.
conversationDaoList.stream().forEach(conversation->delete(conversation));
}
public void delete(ConversationDao conversationDao){
conversationDao.setDeletionTimestamp(new Timestamp(System.currentTimeMillis()));
conversationDatabaseService.save( conversationDao ); <------ This generates 100s of select statements.
}
...
// ConversationDatabaseService Interface
////////////////////////////////////////
public interface ConversationDatabaseService {
void save(ConversationDao conversationDao);
}
...
// Conversation DatabaseService Class
/////////////////////////////////////
#Service
public class ConversationDatabaseServiceImpl implements ConversationDatabaseService {
private final ConversationRepository conversationRepository;
public void save(ConversationDao conversationDao) {
conversationRepository.saveAndFlush(conversationDao); // Just save has also been tried.
}
}
...
// ConversationRepository interface
///////////////////////////////////
public interface ConversationRepository extends JpaRepository<ConversationDao, String> {
List<ConversationDao> findByExpiryDateLessThanAndDeletionTimestampIsNull(Timestamp expiryDate);
}
...
// ConversationDao
//////////////////////////////////
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;
#Entity
#Table(name = "DOCX_CONVERSATION")
public class ConversationDao {
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2",
strategy = "uuid2")
#Column(name = "CONVERSATION_ID",
columnDefinition = "char")
private String conversationId;
#Column(name = "PROCESS_CODE")
private String processCode;
#Column(name = "PROFILE_ID",
columnDefinition = "char")
private String profileId;
#Column(name = "REMINDER_EMAIL_SENT",
columnDefinition = "char")
private String reminderEmailSent;
#Column(name = "EXPIRY_DATE")
private Date expiryDate;
#Column(name = "DELETION_TIMESTAMP")
private Timestamp deletionTimestamp;
#Column(name = "LAST_LOGIN_TIMESTAMP")
private Timestamp lastLoginTimestamp;
#Column(name = "CREATED_USER_ID",
columnDefinition = "char")
private String colleagueId;
#Column(name = "CREATED_TIMESTAMP",
updatable = false)
#CreationTimestamp
private Timestamp createdTimestamp;
#Column(name = "LAST_UPDATED_USER_ID",
columnDefinition = "char")
private String lastUpdatedUserId;
#Column(name = "LAST_UPDATED_TIMESTAMP")
#UpdateTimestamp
private Timestamp lastUpdatedTimestamp;
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<MessageDetailDao> messageDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "fileDetailId.conversation",
cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<ParameterDao> parameterDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<NotificationDao> notificationDaoSet = new HashSet<>();
public ConversationDao() {
}
public ConversationDao(String processCode, Date expiryDate,
String colleagueId, String lastUpdatedUserId) {
this.processCode = processCode;
this.reminderEmailSent = "N";
this.expiryDate = expiryDate;
this.colleagueId = colleagueId;
this.lastUpdatedUserId = lastUpdatedUserId;
}
public String getConversationId() {
return conversationId;
}
public void setConversationId(String conversationId) {
this.conversationId = conversationId;
}
public String getProcessCode() {
return processCode;
}
public void setProcessCode(String processCode) {
this.processCode = processCode;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public String getReminderEmailSent() {
return reminderEmailSent;
}
public void setReminderEmailSent(String reminderEmailSent) {
this.reminderEmailSent = reminderEmailSent;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
public Timestamp getDeletionTimestamp() {
return deletionTimestamp;
}
public void setDeletionTimestamp(Timestamp deletionTimestamp) {
this.deletionTimestamp = deletionTimestamp;
}
public Timestamp getLastLoginTimestamp() {
return lastLoginTimestamp;
}
public void setLastLoginTimestamp(Timestamp lastLoginTimestamp) {
this.lastLoginTimestamp = lastLoginTimestamp;
}
public String getColleagueId() {
return colleagueId.trim();
}
public void setColleagueId(String colleagueId) {
this.colleagueId = colleagueId;
}
public Timestamp getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(Timestamp createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public String getLastUpdatedUserId() {
return lastUpdatedUserId;
}
public void setLastUpdatedUserId(String lastUpdatedUserId) {
this.lastUpdatedUserId = lastUpdatedUserId;
}
public Timestamp getLastUpdatedTimestamp() {
return lastUpdatedTimestamp;
}
public void setLastUpdatedTimestamp(Timestamp lastUpdatedTimestamp) {
this.lastUpdatedTimestamp = lastUpdatedTimestamp;
}
public void addMessageDetailDao(MessageDetailDao messageDetailDao) {
messageDetailDaoSet.add(messageDetailDao);
messageDetailDao.setConversation(this);
}
public Set<MessageDetailDao> getMessageDetailDao() {
return messageDetailDaoSet;
}
public void addFileDetailDao(FileDetailDao fileDetailDao) {
fileDetailDaoSet.add(fileDetailDao);
fileDetailDao.getId().setConversation(this);
}
public Set<FileDetailDao> getFileDetailDao() {
return fileDetailDaoSet;
}
public void addParameterDao(ParameterDao parameterDao) {
parameterDaoSet.add(parameterDao);
parameterDao.setConversation(this);
}
public Set<ParameterDao> getParameterDao() {
return parameterDaoSet;
}
public void addNotificationDao(NotificationDao notificationDao) {
notificationDaoSet.add(notificationDao);
notificationDao.setConversation(this);
}
public Set<NotificationDao> getNotificationDao() {
return notificationDaoSet;
}
}
}
This generates these same select statements 100s of times before blowing the stack :-
1TS="20190411.075004.028" 4MSG="binding parameter [1] as [VARCHAR] - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicBinder"
1TS="20190411.075004.065" 4MSG="extracted value ([convers16_10_0_] : [VARCHAR]) - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.069" 4MSG="extracted value ([file_met1_10_0_] : [VARCHAR]) - [4E90FD20-FC59-41B8-BF8E-88B7D682A87C]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.074" 4MSG="select conversati0_.conversation_id as conversa1_5_1_, conversati0_.created_user_id as created_2_5_1_, conversati0_.created_timestamp as created_3_5_1_, conversati0_.deletion_timestamp as deletion4_5_1_, conversati0_.expiry_date as expiry_d5_5_1_, conversati0_.last_login_timestamp as last_log6_5_1_, conversati0_.last_updated_timestamp as last_upd7_5_1_, conversati0_.last_updated_user_id as last_upd8_5_1_, conversati0_.process_code as process_9_5_1_, conversati0_.profile_id as profile10_5_1_, conversati0_.reminder_email_sent as reminde11_5_1_, filedetail1_.conversation_id as convers16_10_3_, filedetail1_.file_metadata_id as file_met1_10_3_, filedetail1_.conversation_id as convers16_10_0_, filedetail1_.file_metadata_id as file_met1_10_0_, filedetail1_.application_id as applicat2_10_0_, filedetail1_.case_id as case_id3_10_0_, filedetail1_.created_user_id as created_4_10_0_, filedetail1_.content_type as content_5_10_0_, filedetail1_.created_by as created_6_10_0_, filedetail1_.created_timestamp as created_7_10_0_, filedetail1_.document_code as document8_10_0_, filedetail1_.document_owner as document9_10_0_, filedetail1_.document_repository_state as documen10_10_0_, filedetail1_.file_name as file_na11_10_0_, filedetail1_.file_size_bytes as file_si12_10_0_, filedetail1_.file_state as file_st13_10_0_, filedetail1_.file_version as file_ve14_10_0_, filedetail1_.updated_by as updated15_10_0_ from docx_conversation conversati0_ left outer join docx_file_detail filedetail1_ on conversati0_.conversation_id=filedetail1_.conversation_id where conversati0_.conversation_id=?" 1EVC="DEBUG" 2CLS="SQL"
What is going on ??
Some more information, the cause is definitely connected to this part of the dao :-
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
The FileDetailDao contains an embedded reference to a FileDetailId
#EmbeddedId
private FileDetailId fileDetailId;
And this FileDetailId contains a reference to the conversationId of the join :-
#Embeddable
public class FileDetailId implements Serializable {
#Column(name = "FILE_METADATA_ID", columnDefinition = "char")
private String fileMetadataId;
#ManyToOne
#JoinColumn(name = "CONVERSATION_ID")
private ConversationDao conversation;
//etc
}
Im not sure why but if I change the cascade type to REMOVE it works ok....
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.REMOVE)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();

Convert String or int To Enum in JPA

I don't know how I can persist an entity(with enum) to the database.
When I fill my form like this;
form.setTypZamowienia(SlownikZamowienie.SENIOR)
then 666 is stored in the database. But when I try like this;
form.setTypZamowienia(SlownikZamowienie.valueOf(request.getParameter("typKlienta").trim()));
0 is stored in the database.
How do I make this work?
For any help I will be very grateful.
My enum :
public enum SlownikZamowienie
{
JUNIOR(42),
SENIOR(666),
PRINCIPAL(31416);
private final int wartosc;
SlownikZamowienie(int wartosc) {
this.wartosc = wartosc;
}
}
My Entity:
package test.jpa.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import test.enums.SlownikZamowienie;
#Entity
#Table(name="Piess")
public class Pies implements Serializable {
private static final Long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
int id;
#Column(name = "imie")
String imie;
#Enumerated
#Column(name = "rasa")
SlownikZamowienie typzamowienia;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImie() {
return imie;
}
public void setImie(String imie) {
this.imie = imie;
}
public SlownikZamowienie getTypzamowienia() {
return typzamowienia;
}
public void setTypzamowienia(SlownikZamowienie typzamowienia) {
this.typzamowienia = typzamowienia;
}
}
As of JPA 2.1 you can use an attribute converter (known as a UserType in the Hibernate world). See these two articles for details on how to implement such a solution:
www.thoughts-on-java.org/jpa-21-type-converter-better-way-to/
www.thoughts-on-java.org/jpa-21-how-to-implement-type-converter/