Trying to do a simple select from Java service layer here is my Model:
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
#Entity
#Table(name="PROF_INFO")
public class ProfileInfo {
#EmbeddedId
private ProfileInfoPK profileInfoPK;
#Column(name="RATING", nullable = true )
private Integer rating;
#Column(name="VIEW_DATE", nullable = false )
private java.util.Date viewDate;
#Column(name="CONTACT_DATE", nullable = true )
private java.util.Date contactDate;
#Column(name="REPORTED_DATE", nullable = true )
private java.util.Date reportedDate;
#Column(name="REPORTED_TYPE", nullable = true )
private Integer reportedType;
#Column(name="REPORTED_COMMENT", nullable = true )
private String reportedComment;
public Integer getRating(){
return this.rating;
}
public void setRating(Integer rating){
this.rating = rating;
}
public java.util.Date getViewDate(){
return this.viewDate;
}
public void setViewDate(java.util.Date viewDate){
this.viewDate = viewDate;
}
public java.util.Date getContactDate(){
return this.contactDate;
}
public void setContactDate(java.util.Date contactDate){
this.contactDate = contactDate;
}
public java.util.Date getReportedDate(){
return this.reportedDate;
}
public void setReportedDate(java.util.Date reportedDate){
this.reportedDate = reportedDate;
}
public Integer getReportedType(){
return this.reportedType;
}
public void setReportedType(Integer reportedType){
this.reportedType = reportedType;
}
public String getReportedComment(){
return this.reportedComment;
}
public void setReportedComment(String reportedComment){
this.reportedComment = reportedComment;
}
#Embeddable
public static class ProfileInfoPK implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Column(name="PST_USER_ID", nullable = false )
private Integer pstUserId;
#Column(name="FILE_NAME", nullable = false )
private String fileName;
public Integer getPstUserId() {
return pstUserId;
}
public void setPstUserId(Integer pstUserId) {
this.pstUserId = pstUserId;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((fileName == null) ? 0 : fileName.hashCode());
result = prime * result
+ ((pstUserId == null) ? 0 : pstUserId.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProfileInfoPK other = (ProfileInfoPK) obj;
if (fileName == null) {
if (other.fileName != null)
return false;
} else if (!fileName.equals(other.fileName))
return false;
if (pstUserId == null) {
if (other.pstUserId != null)
return false;
} else if (!pstUserId.equals(other.pstUserId))
return false;
return true;
}
}
public ProfileInfoPK getProfileInfoPK() {
return profileInfoPK;
}
public void setProfileInfoPK(ProfileInfoPK profileInfoPK) {
this.profileInfoPK = profileInfoPK;
}
}
Here is my DAOImpl:
public List<ProfileInfo> getByEntityandFileName(String entityId,
String fileName)throws NoSuchProfileInfoException , SystemException{
Query query = null;
List<ProfileInfo> results = null;
try{
query = sessionFactory.
getCurrentSession().
createQuery("from ProfileInfo where PST_USER_ID = :PST_USER_ID"); //AND FILE_NAME IN (:FILE_NAME)");
query.setParameter("PST_USER_ID", entityId);
//query.setParameterList("FILE_NAME", fileName.split("\\s*,\\s*"));
}catch(Exception ex){
throw new SystemException(ex);
}
if (query != null) {
results = query.list();
}else{
throw new SystemException("Query Null");
}
if (null != results && !results.isEmpty()) {
return results;
} else {
throw new NoSuchProfileInfoException("No Results Returned");
}
}
}
The db has the PK index on PST_USER_ID,FILE_NAME
and a desc
desc PROF_INFO
Name Null Type
---------------- -------- --------------
PST_USER_ID NOT NULL NUMBER(38)
FILE_NAME NOT NULL VARCHAR2(32)
RATING NUMBER(38)
VIEW_DATE NOT NULL DATE
CONTACT_DATE DATE
REPORTED_DATE DATE
REPORTED_TYPE NUMBER
REPORTED_COMMENT VARCHAR2(1000)
All seems straight forward enough however when I try and query back I receive the following error:
org.hibernate.hql.internal.ast.QuerySyntaxException: ProfileInfo is not mapped [from ProfileInfo where PST_USER_ID = :PST_USER_ID]
Not sure what the culprit is but something has gone up the left. Anything look out of place to you guys and girls?
You have mixed pur SQL with HQL. It should be
createQuery("from ProfileInfo where profileInfoPK.pstUserId = :PST_USER_ID");
check the profileInfoPK.pstUserId part.
In HQLs, you can not refer to the table name or its column names. Instead you have to use the mapped class and its properties.
You could check following things:
Can you check Hibernate configuration file for class mapping details ?
Can you could test without parameter then with parameter?
createQuery("from ProfileInfo " );
createQuery("from ProfileInfo pfi where pfi.profileInfoPK.pstUserId = :pstUserID");
Related
I have a code like this:
public interface BatchExecuteHistoryRepository extends JpaRepository<BatchExecuteHistory, Long> {
Page<BatchExecuteHistory> findByBatchExecuteHistoryIdBatchIdOrderByTimeEndAsc(String batchId, Pageable pageable);
}
Here is my database:
Here is what I got on my website:
Anyone know why the query does not work with Order By time_end ASC???
I tried findByBatchExecuteHistoryIdBatchId(String batchId, Pageable pageable) and got the same result
Notice that BatchExecuteHistoryId is a composite id, and batchId is a element of it
Update, here is my BatchExecuteHistory class:
public class BatchExecuteHistory implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private BatchExecuteHistoryId batchExecuteHistoryId;
#NotNull
#Size(max = 100)
#Column(name = "batch_name", length = 100, nullable = false)
private String batchName;
#NotNull
#Column(name = "status", nullable = false)
private Boolean status;
#NotNull
#Column(name = "time_end", nullable = false)
private Instant timeEnd;
#Size(max = 100)
#Column(name = "error_step", length = 100)
private String errorStep;
#Size(max = 100)
#Column(name = "error_content", length = 100)
private String errorContent;
#Column(name = "row_input")
private Long rowInput;
public BatchExecuteHistoryId getBatchExecuteHistoryId() {
return batchExecuteHistoryId;
}
public void setBatchExecuteHistoryId(BatchExecuteHistoryId batchExecuteHistoryId) {
this.batchExecuteHistoryId = batchExecuteHistoryId;
}
public Boolean getStatus() {
return status;
}
public String getBatchName() {
return batchName;
}
public BatchExecuteHistory batchName(String batchName) {
this.batchName = batchName;
return this;
}
public void setBatchName(String batchName) {
this.batchName = batchName;
}
public Boolean isStatus() {
return status;
}
public BatchExecuteHistory status(Boolean status) {
this.status = status;
return this;
}
public void setStatus(Boolean status) {
this.status = status;
}
public Instant getTimeEnd() {
return timeEnd;
}
public BatchExecuteHistory timeEnd(Instant timeEnd) {
this.timeEnd = timeEnd;
return this;
}
public void setTimeEnd(Instant timeEnd) {
this.timeEnd = timeEnd;
}
public String getErrorStep() {
return errorStep;
}
public BatchExecuteHistory errorStep(String errorStep) {
this.errorStep = errorStep;
return this;
}
public void setErrorStep(String errorStep) {
this.errorStep = errorStep;
}
public String getErrorContent() {
return errorContent;
}
public BatchExecuteHistory errorContent(String errorContent) {
this.errorContent = errorContent;
return this;
}
public void setErrorContent(String errorContent) {
this.errorContent = errorContent;
}
public Long getRowInput() {
return rowInput;
}
public BatchExecuteHistory rowInput(Long rowInput) {
this.rowInput = rowInput;
return this;
}
public void setRowInput(Long rowInput) {
this.rowInput = rowInput;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((batchExecuteHistoryId == null) ? 0 : batchExecuteHistoryId.hashCode());
result = prime * result + ((batchName == null) ? 0 : batchName.hashCode());
result = prime * result + ((errorContent == null) ? 0 : errorContent.hashCode());
result = prime * result + ((errorStep == null) ? 0 : errorStep.hashCode());
result = prime * result + ((rowInput == null) ? 0 : rowInput.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
result = prime * result + ((timeEnd == null) ? 0 : timeEnd.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BatchExecuteHistory other = (BatchExecuteHistory) obj;
if (batchExecuteHistoryId == null) {
if (other.batchExecuteHistoryId != null)
return false;
} else if (!batchExecuteHistoryId.equals(other.batchExecuteHistoryId))
return false;
if (batchName == null) {
if (other.batchName != null)
return false;
} else if (!batchName.equals(other.batchName))
return false;
if (errorContent == null) {
if (other.errorContent != null)
return false;
} else if (!errorContent.equals(other.errorContent))
return false;
if (errorStep == null) {
if (other.errorStep != null)
return false;
} else if (!errorStep.equals(other.errorStep))
return false;
if (rowInput == null) {
if (other.rowInput != null)
return false;
} else if (!rowInput.equals(other.rowInput))
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
if (timeEnd == null) {
if (other.timeEnd != null)
return false;
} else if (!timeEnd.equals(other.timeEnd))
return false;
return true;
}
#Override
public String toString() {
return "BatchExecuteHistory [" + batchExecuteHistoryId.toString() + ", batchName=" + batchName + ", status="
+ status + ", timeEnd=" + timeEnd + ", errorStep=" + errorStep + ", errorContent=" + errorContent
+ ", rowInput=" + rowInput + "]";
}
}
You should add a By before OrderBy, so your method should be: findByBatchExecuteHistoryIdBatchIdByOrderByTimeEndAsc
I think you don't miss naming.See Spring document
OrderBy
findByAgeOrderByLastnameDesc
… where x.age = ?1 order by x.lastname desc
It works well in my environment. I am using 2.6.0 version.
I recommand you check jpa version.and I can't see your BatchExecuteHistoryId class.
Anyway Try it for checking it works well in your environment.
Database
CREATE TABLE MEMBER
(
id character varying(10),
batch_id character varying(10),
create_datetime timestamp without time zone NOT NULL,
CONSTRAINT MEMBER_PK
PRIMARY KEY (id,batch_id)
);
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER1','2021/11/20 14:00:00','1');
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER2','2021/11/15 14:00:00','1');
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER3','2021/11/10 14:00:00','1');
Entity
#Entity(name = "Member")
#Table(name = "member")
#ToString
#Data
public class MemberEntity {
#EmbeddedId
private MemberPk batchExecuteHistoryId;
#Column(name = "create_datetime")
private LocalDateTime createDateTime;
}
Pk of Entity
#Embeddable
#ToString
public class MemberPk implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
#Column(name = "batch_id")
private String batchId;
}
Repository
#Repository
public interface MemberRepository extends JpaRepository<MemberEntity, String> {
public List<MemberEntity> findByBatchExecuteHistoryIdBatchIdOrderByCreateDateTimeAsc(String batchId, Pageable pageable);
}
Service
#Service
public class MemberService {
private final MemberRepository memberRepository;
#Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
#PostConstruct
public void findAllMember() {
List<MemberEntity> memberEntitys = memberRepository.findAll();
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER1, batchId=1), createDateTime=2021-11-20T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER2, batchId=1), createDateTime=2021-11-15T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER3, batchId=1), createDateTime=2021-11-10T14:00)
memberEntitys.forEach(System.out::println);
System.out.println("----------------------------");
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER3, batchId=1), createDateTime=2021-11-10T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER2, batchId=1), createDateTime=2021-11-15T14:00)
List<MemberEntity> memberEntitysWithOrderBy = memberRepository.findByBatchExecuteHistoryIdBatchIdOrderByCreateDateTimeAsc("1",PageRequest.of(0, 2));
memberEntitysWithOrderBy.forEach(System.out::println);
}
}
I have this JPA method which fetches a list of "to do" between 2 dates from the database using a query.
public List<Tarea> findTareasEntreFechas(Long idUsuario, Date fechaInicio, Date fechaFin) {
return jpaApi.withTransaction(entityManager -> {
TypedQuery<Tarea> query = entityManager.createQuery(
"SELECT t "
+ "FROM Tarea t "
+ "WHERE usuario.id = :userId "
+ "AND t.hecha is FALSE "
+ "AND t.fechaFinalizacion >= :fechaInicio "
+ "AND t.fechaFinalizacion <= :fechaFin "
, Tarea.class);
try {
List<Tarea> tareas = query.setParameter("userId", idUsuario)
.setParameter("fechaInicio", fechaInicio)
.setParameter("fechaFin", fechaFin)
.getResultList();
return tareas;
}
catch(NoResultException ex) {
return null;
}
});
}
And this is my Tarea entity.
package models;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
#Entity
public class Tarea {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String titulo;
// Relación muchos-a-uno entre tareas y usuario
#ManyToOne
// Nombre de la columna en la BD que guarda físicamente
// el ID del usuario con el que está asociado una tarea
#JoinColumn(name = "usuarioId")
public Usuario usuario;
private Boolean hecha;
#Temporal(TemporalType.DATE)
private Date fechaCreacion;
#Temporal(TemporalType.DATE)
private Date fechaFinalizacion;
#ManyToOne
#JoinColumn(name = "tareaPadreId")
private Tarea tareaPadre;
#OneToMany(mappedBy="tareaPadre", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE, orphanRemoval = true)
public Set<Tarea> subtareas = new HashSet<Tarea>();
public Tarea() {
this.hecha = false;
}
public Tarea(Usuario usuario, String titulo) {
this.usuario = usuario;
this.titulo = titulo;
this.hecha = false;
this.fechaCreacion = Calendar.getInstance().getTime();
}
public Tarea(Usuario usuario, String titulo, Date fechaFinalizacion) {
this.usuario = usuario;
this.titulo = titulo;
this.hecha = false;
this.fechaCreacion = Calendar.getInstance().getTime();
this.fechaFinalizacion = fechaFinalizacion;
}
// Getters y setters necesarios para JPA
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public Boolean getHecha() { return hecha; }
public void setHecha(Boolean hecha) { this.hecha = hecha; }
public Date getFechaCreacion() {
return fechaCreacion;
}
public Date getFechaFinalizacion() {
return fechaFinalizacion;
}
public String getFechaFinalizacionFormateada() {
Date fechaFinalizacion = getFechaFinalizacion();
if(fechaFinalizacion != null) {
return (new SimpleDateFormat("dd-MM-yyyy")).format(fechaFinalizacion);
}
return "";
}
public void setFechaFinalizacion(Date fechaFinalizacion) {
this.fechaFinalizacion = fechaFinalizacion;
}
public boolean isRetrasada() {
if(fechaFinalizacion != null) {
Date ahora = new Date();
return ahora.after(fechaFinalizacion);
}
return false;
}
public String toString() {
return String.format("Tarea id: %s titulo: %s usuario: %s hecha: %s", id, titulo, usuario.toString(), hecha ? "si" : "no");
}
#Override
public int hashCode() {
final int prime = 31;
int result = prime + ((titulo == null) ? 0 : titulo.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (getClass() != obj.getClass()) return false;
Tarea other = (Tarea) obj;
// Si tenemos los ID, comparamos por ID
if (id != null && other.id != null)
return ((long) id == (long) other.id);
// sino comparamos por campos obligatorios
else {
if (titulo == null) {
if (other.titulo != null) return false;
} else if (!titulo.equals(other.titulo)) return false;
if (usuario == null) {
if (other.usuario != null) return false;
else if (!usuario.equals(other.usuario)) return false;
}
if (hecha == null) {
if (other.hecha != null) return false;
else if (!hecha.equals(other.hecha)) return false;
}
}
return true;
}
public Tarea getTareaPadre() {
return tareaPadre;
}
public void setTareaPadre(Tarea tareaPadre) {
this.tareaPadre = tareaPadre;
}
public Set<Tarea> getSubtareas() {
return subtareas;
}
public void setSubtareas(Set<Tarea> subtareas) {
this.subtareas = subtareas;
}
}
The problem is that when I call this method from the controller and I try to serialize the returned List into JSON, It throws this exception:
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)
Furthermore, It doesn't happen when I manually parse the result into a String.
The point of the question is that every solution I find says that I have to put the annotation #JsonIgnore in one side of the relationship. I've tried that but doesn't seem to work, because the relationship itself retrieves all the "to do" of the User...
Putting my comments in the form of an answer.
Your Tarea entity yields both references to a parent and a Set of children.
What happens when top entities are serialized to JSON is their children get included in the JSON.
But since the children contain a reference to their parent, their parent is serialized again too, for each child.
And as the parent also yields a reference to each child, etc. etc. etc. you can see how that would generate "infinite" JSON and produce a stack overflow.
The solution would be to ensure at least the reference to the parent is ignored (#JsonIgnore) when serializing, although you may also ignore the reference to children to avoid verbosity.
Speculatively digging further, if your user entity Usuario also links to task entities Tareas, you may need to ignore those fields in the user as well (which you seem to have tried already, but that may not be the issue or only part of it).
There are two solutions to this. One is using #JsonIgnore as mentioned, the other is combining #JsonManagedReference and #JsonBackReference.
The first one goes in the parent class, the second in the child class. Since those classes are the same one in this instance, it might be an problem if the recursion bug is not fixed in the respective version of Jackson.
Try this (no guarantees, as I've only used it with different classes)
#JsonBackReference
private Tarea tareaPadre;
#JsonManagedReference
public Set<Tarea> subtareas = new HashSet<Tarea>();
This also helps with deserialization, as the child-objects are automatically set to point to their parent.
I only need to get first name and last name into attribute ownerName and for me the best solution would be if I just call the setter for ownerName in setter of conversationOwner but with this I am getting error:
Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Exception occurred inside setter of medictonproject.model.ConversationEntity.conversationOwner
Here is the Entity class:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.*;
import org.hibernate.annotations.CascadeType;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "conversation", schema = "swprojekt")
public class ConversationEntity {
private int conversationId;
private String title;
private Timestamp beginningDate;
#JsonIgnore
private UserEntity conversationOwner;
private String ownerName;
#JsonIgnore
private List<MessageEntity> messages = new ArrayList<>();
private MessageEntity firstMessage;
private boolean seen;
#Transient
public MessageEntity getFirstMessage() {
return firstMessage;
}
public void setFirstMessage(MessageEntity firstMessage) {
this.firstMessage = firstMessage;
}
#Transient
public boolean isSeen() {
return seen;
}
public void setSeen( boolean seen ) {
this.seen = seen;
}
#OneToMany(mappedBy="conversation", cascade = javax.persistence.CascadeType.ALL)
public List<MessageEntity> getMessages() {
return messages;
}
public void setMessages(List<MessageEntity> messages) {
this.messages = messages;
}
#ManyToOne(fetch=FetchType.LAZY, cascade = javax.persistence.CascadeType.ALL)
#JoinColumn(name="user_id")
public UserEntity getConversationOwner() {
return conversationOwner;
}
public void setConversationOwner(UserEntity conversationOwner) {
this.conversationOwner = conversationOwner;
setOwnerName();
}
#Transient
public String getOwnerName() {
return ownerName;
}
public void setOwnerName() {
this.ownerName = conversationOwner.getFirstName() + " " + conversationOwner.getLastName();
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "conversation_id", nullable = false)
public int getConversationId() {
return conversationId;
}
public void setConversationId(int conversationId) {
this.conversationId = conversationId;
}
#Basic
#Column(name = "title", nullable = false, length = 200)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Basic
#Column(name = "beginning_date", nullable = false)
public Timestamp getBeginningDate() {
return beginningDate;
}
public void setBeginningDate(Timestamp beginningDate) {
this.beginningDate = beginningDate;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConversationEntity that = (ConversationEntity) o;
if (conversationId != that.conversationId) return false;
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (beginningDate != null ? !beginningDate.equals(that.beginningDate) : that.beginningDate != null)
return false;
return true;
}
#Override
public int hashCode() {
int result = conversationId;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (beginningDate != null ? beginningDate.hashCode() : 0);
return result;
}
}
I have a Canteen class and a Course class (and a BaseEntity). The Canteen class has a set of courses. A course is unique if the composition of name, dateOfServing and the canteen id is unique. I tried to write a test case which should throw an exception if a non-unique course is added to a canteen. But the test doesn't throw any exception at all. Which leads me to believe that I'm doing me Canteen and Course class wrong. The test in question is addDuplicatedCourseToCanteenTest. Anyone got a clue about what I'm doing wrong?
I'm new to TDD as well so any critique in that area is very welcome as well.
BaseEntity.java
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
private Date createdAt;
private Date updatedAt;
// TODO: http://stackoverflow.com/a/11174297/672009
// Using the above we wouldn't have to created a CommentRepository
// Is that a good idea?
/**
* http://www.devsniper.com/base-entity-class-in-jpa/
*/
/**
* Sets createdAt before insert
*/
#PrePersist
public void setCreationDate() {
this.setCreatedAt(new Date());
}
/**
* Sets updatedAt before update
*/
#PreUpdate
public void setChangeDate() {
this.setUpdatedAt(new Date());
}
public Date getCreatedAt() {
return createdAt;
}
protected void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
protected void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseEntity other = (BaseEntity) obj;
if (id != other.id)
return false;
return true;
}
}
Canteen.java
#Entity
public class Canteen extends BaseEntity {
private String name;
// TODO: https://schuchert.wikispaces.com/JPA+Tutorial+1+-+Embedded+Entity
// http://docs.oracle.com/javaee/6/api/javax/xml/registry/infomodel/PostalAddress.html
//private Address address;
//private PostalAddress postalAddress;
/**
* In honor of KISS I simply use a simple string address as a holder for the restaurants address.
* The idea is that the string will contain an address which will be valid according to google maps.
* Same goes for openingHours, phoneNumber and homepage... KISS wise.
*/
private String address;
private String openingHours; // A string which will be presented within a pre tag
// Eg. <pre>Mandag - Torsdag 10-22
// Fredag - Lørdag 10-24
// Søndag 11-20</pre>
private String contact;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Course> courses = new HashSet<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getOpeningHours() {
return openingHours;
}
public void setOpeningHours(String openingHours) {
this.openingHours = openingHours;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public boolean addCourse(Course course)
{
return getCourses().add(course);
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Canteen other = (Canteen) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Course.java
#Entity
public class Course extends BaseEntity {
private String name;
private Date dateOfServing;
#ManyToOne
private Canteen canteen;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDateOfServing() {
return dateOfServing;
}
public void setDateOfServing(Date dateOfServing) {
this.dateOfServing = dateOfServing;
}
public Canteen getCanteen() {
return canteen;
}
public void setCanteen(Canteen canteen) {
this.canteen = canteen;
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((canteen == null) ? 0 : canteen.hashCode());
result = prime * result
+ ((dateOfServing == null) ? 0 : dateOfServing.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Course other = (Course) obj;
if (canteen == null) {
if (other.canteen != null)
return false;
} else if (!canteen.equals(other.canteen))
return false;
if (dateOfServing == null) {
if (other.dateOfServing != null)
return false;
} else if (!dateOfServing.equals(other.dateOfServing))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
CanteenHasCoursesTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = PersistenceConfig.class)
public class CanteenHasCoursesTest {
#Autowired
private CanteenRepository canteenRepository;
private String canteenName;
private String courseName;
private Canteen canteen;
private Course course;
#Before
public void setUp() {
// Generate unique random name
canteenName = UUID.randomUUID().toString();
// Generate unique random name
courseName = UUID.randomUUID().toString();
// Create new canteen
canteen = new Canteen();
canteen.setName(canteenName);
// Create new course
course = new Course();
course.setName(courseName);
}
#Test
public void addCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
// Find it again
Canteen c = canteenRepository.findOne(canteen.getId());
// Confirm attributes are as expected
assertNotNull(c);
Set<Course> courses = c.getCourses();
Iterator<Course> it = courses.iterator();
assertTrue(it.hasNext());
Course course = it.next();
assertEquals(courseName, course.getName());
}
// TODO: expect some data violation exception
// #Test(expected = IndexOutOfBoundsException.class)
#Test
public void addDuplicatedCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Add it again
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
}
#After
public void tearDown() {
canteenRepository = null;
canteenName = null;
courseName = null;
canteen = null;
course = null;
}
}
I have a basic problem with my oracle database table whereas I use JPA.
My problem is, I create the table in the database by adding it an ID column. When I turn back to my JPA project, and when I try to create new entry it doesn't create ID for the new one. It always says: An error occurred attempting to roll back the transaction.
I search about the issue. It basically doesn't auto-generate the ID value. Here is my JPA controller class:
#Entity
#Table(name = "PROJECTS", catalog = "", schema = "PROJETAKIP")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Projects.findAll", query = "SELECT p FROM Projects p"),
#NamedQuery(name = "Projects.findById", query = "SELECT p FROM Projects p WHERE p.id = :id"),
#NamedQuery(name = "Projects.findByProject", query = "SELECT p FROM Projects p WHERE p.project = :project")})
public class Projects implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#Column(name = "ID", nullable = false, precision = 0, scale = -127)
#GeneratedValue(strategy= GenerationType.SEQUENCE)
private BigDecimal id;
#Column(name = "PROJECT", length = 255)
private String project;
public Projects() {
}
public Projects(BigDecimal id) {
this.id = id;
}
public BigDecimal getId() {
return id;
}
public void setId(BigDecimal id) {
this.id = id;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Projects)) {
return false;
}
Projects other = (Projects) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.ibb.souce.Projects[ id=" + id + " ]";
}
}
and here is my JSFClass:
#ManagedBean(name = "projectsController")
#SessionScoped
public class ProjectsController implements Serializable {
#Resource
private UserTransaction utx = null;
#PersistenceUnit(unitName = "DenemelerPU")
private EntityManagerFactory emf = null;
private Projects current;
private DataModel items = null;
private ProjectsJpaController jpaController = null;
private PaginationHelper pagination;
private int selectedItemIndex;
public ProjectsController() {
}
public Projects getSelected() {
if (current == null) {
current = new Projects();
selectedItemIndex = -1;
}
return current;
}
private ProjectsJpaController getJpaController() {
if (jpaController == null) {
jpaController = new ProjectsJpaController(utx, emf);
}
return jpaController;
}
public PaginationHelper getPagination() {
if (pagination == null) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return getJpaController().getProjectsCount();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(getJpaController().findProjectsEntities(getPageSize(), getPageFirstItem()));
}
};
}
return pagination;
}
public String prepareList() {
recreateModel();
return "List";
}
public String prepareView() {
current = (Projects) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "View";
}
public String prepareCreate() {
current = new Projects();
selectedItemIndex = -1;
return "Create";
}
public String create() {
try {
getJpaController().create(current);
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("ProjectsCreated"));
return prepareCreate();
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
public String prepareEdit() {
current = (Projects) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "Edit";
}
public String update() {
try {
getJpaController().edit(current);
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("ProjectsUpdated"));
return "View";
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
public String destroy() {
current = (Projects) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
performDestroy();
recreatePagination();
recreateModel();
return "List";
}
public String destroyAndView() {
performDestroy();
recreateModel();
updateCurrentItem();
if (selectedItemIndex >= 0) {
return "View";
} else {
// all items were removed - go back to list
recreateModel();
return "List";
}
}
private void performDestroy() {
try {
getJpaController().destroy(current.getId());
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("ProjectsDeleted"));
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
private void updateCurrentItem() {
int count = getJpaController().getProjectsCount();
if (selectedItemIndex >= count) {
// selected index cannot be bigger than number of items:
selectedItemIndex = count - 1;
// go to previous page if last page disappeared:
if (pagination.getPageFirstItem() >= count) {
pagination.previousPage();
}
}
if (selectedItemIndex >= 0) {
current = getJpaController().findProjectsEntities(1, selectedItemIndex).get(0);
}
}
public DataModel getItems() {
if (items == null) {
items = getPagination().createPageDataModel();
}
return items;
}
private void recreateModel() {
items = null;
}
private void recreatePagination() {
pagination = null;
}
public String next() {
getPagination().nextPage();
recreateModel();
return "List";
}
public String previous() {
getPagination().previousPage();
recreateModel();
return "List";
}
public SelectItem[] getItemsAvailableSelectMany() {
return JsfUtil.getSelectItems(getJpaController().findProjectsEntities(), false);
}
public SelectItem[] getItemsAvailableSelectOne() {
return JsfUtil.getSelectItems(getJpaController().findProjectsEntities(), true);
}
#FacesConverter(forClass = Projects.class)
public static class ProjectsControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
ProjectsController controller = (ProjectsController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "projectsController");
return controller.getJpaController().findProjects(getKey(value));
}
java.math.BigDecimal getKey(String value) {
java.math.BigDecimal key;
key = new java.math.BigDecimal(value);
return key;
}
String getStringKey(java.math.BigDecimal value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Projects) {
Projects o = (Projects) object;
return getStringKey(o.getId());
} else {
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + Projects.class.getName());
}
}
}
}
When I assign the ID manually it works perfectly. But what I want is, it has to auto-generate the value. How to overcome this?
my trigger: DELIMITER ##
CREATE OR REPLACE TRIGGER PROJETAKIP.PROJECTS_TRIGGER BEFORE INSERT ON PROJECTS REFERENCING NEW AS NEW FOR EACH ROW BEGIN SELECT PROJECTS_SEQUENCE.nextval INTO :NEW.ID FROM dual;END; ##
DELIMITER ;
Sequence startegy
This is how you should use the sequence generator:
#GeneratedValue(strategy= GenerationType.SEQUENCE, generator="seq")
And on the class: (eg. after the #Entity)
#SequenceGenerator(name="seq", sequenceName="PROJECTS_SEQUENCE", initialValue=1)
This should work for you.
While saving the object i had the same error.
My reason was because of adding MIN range of 3 digits to id value.
By default auto generated id will start from 1, 2, 3 ...
I did:
#Id #GeneratedValue
#Basic(optional = false)
#Size(min = 1, max = 64, message = "ID must be between 1 and 64 characters")
private String id;
So - in your case - be careful with your id annotations - try to launch without scale, min and max values - see the result. For example, try:
#Id
#Basic(optional = false)
#Column(name = "ID")
#GeneratedValue(strategy= GenerationType.AUTO)
private BigDecimal id;