JPA Hibernate Saving ManyToOne field is null - java

I have a servlet method that creates a JPA entity and assigns an existing JPA entity to a #ManyToOne field
When I persist it, it saves the entity but the foreign key is NULL. Why?
Here are my entities:
#Entity
public class SimpleEntity implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -5930519292861829894L;
#Id #GeneratedValue
Long id;
String name;
#ManyToOne()
#JoinColumn(name="simple_entity_group_id", insertable=false, updatable=false, nullable=true)
SimpleEntityGroup group;
/**
*
*/
public SimpleEntity() {
}
/**
* #return the id
*/
public Long getId() {
return this.id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return this.name;
}
/**
* #param name the name to set
*/
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "SimpleEntity [id=" + this.id + ", name=" + this.name + ", group=" + this.getGroup() + "]";
}
/**
* #return the group
*/
public SimpleEntityGroup getGroup() {
return this.group;
}
/**
* #param group the group to set
*/
public void setGroup(SimpleEntityGroup group) {
this.group = group;
}
}
#Entity
public class SimpleEntityGroup implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1680386377742600266L;
#Id #GeneratedValue
Long id;
String name;
#OneToMany(mappedBy="group")
java.util.List<SimpleEntity> simpleEntities;
/**
*
*/
public SimpleEntityGroup() {
simpleEntities = new ArrayList<SimpleEntity>();
}
/**
* #return the id
*/
public Long getId() {
return this.id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return this.name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the simpleEntities
*/
public java.util.List<SimpleEntity> getSimpleEntities() {
return this.simpleEntities;
}
/**
* #param simpleEntities the simpleEntities to set
*/
public void setSimpleEntities(java.util.List<SimpleEntity> simpleEntities) {
this.simpleEntities = simpleEntities;
}
public void addSimpleEntity(SimpleEntity e) {
if(this.getSimpleEntities() != null) {
this.getSimpleEntities().add(e);
return;
}
throw new RuntimeException("Entity list is null!!!");
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "SimpleEntityGroup [id=" + this.id + ", name=" + this.name + "]";
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SimpleEntityGroup other = (SimpleEntityGroup) obj;
if (this.id == null) {
if (other.id != null) {
return false;
}
} else if (!this.id.equals(other.id)) {
return false;
}
return true;
}
}
Here is how I persist it:
SimpleEntity e = new SimpleEntity();
e.setName("Mike");
SimpleEntityGroup g = dao.getGroupById(1l);
e.setGroup(g);
dao.persist(e);
System.out.println(e);
System.out.println(dao.findAll());
Here is the output from the Java code, the group is set on the entry but it is not saved. Why?!?!
SimpleEntity [id=4, name=Mike, group=SimpleEntityGroup [id=1,
name=Group 1]]
[SimpleEntity [id=4, name=Mike, group=null]]

Of course I just figured it out, needed to do:
#ManyToOne()
#JoinColumn(name="simple_entity_group_id")
SimpleEntityGroup group;
-- Got rid of the insert=false, update=false

You only posted your child class but I think will be better if you also include the parent class code. I had the same problem when I tried make saves in cascade using only auto generated ids. I could solve it using the next annotations.
In my parent class I have
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="IDCOBPRES", unique=true, nullable=false)
public Long getIdcobpres() {
return this.idcobpres;
}
//....
#OneToMany(fetch=FetchType.LAZY, mappedBy="cobpresGestion")
#Cascade({CascadeType.ALL})
public Set<CobpresOptionDet> getCobpresOptionDets() {
return this.cobpresOptionDets;
}
In my child class I have
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="IDOPTIONDET", unique=true, nullable=false)
public Long getIdoptiondet() {
return this.idoptiondet;
}
//...
#ManyToOne(fetch=FetchType.LAZY, optional=false)
#JoinColumn(name="IDCOBPRES", nullable=false, insertable=true, updatable=true)
public CobpresGestion getCobpresGestion() {
return this.cobpresGestion;
}

Related

Spring Mongodb pagination of nested collection field

I have a collection of document inside another document. Would like to implement pagination on nested element while fetching the data. Could you please let me know how to do that? In the structure I would like to fetch messages using pagination.
public abstract class CommonDomainAttributes implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
#Id
protected String id;
#JsonIgnore
#CreatedDate
protected Date createDate;
//#JsonIgnore
#LastModifiedDate
//#JsonSerialize(using=JsonDateSerializer.class)
protected Date lastModifiedDate;
#JsonIgnore
#CreatedBy
protected String createdBy;
#JsonIgnore
#LastModifiedBy
protected String lastModifiedBy;
/**
* #return the id
*/
public String getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* #return the createDate
*/
public Date getCreateDate() {
return createDate;
}
/**
* #param createDate the createDate to set
*/
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
/**
* #return the lastModifiedDate
*/
public Date getLastModifiedDate() {
return lastModifiedDate;
}
/**
* #param lastModifiedDate the lastModifiedDate to set
*/
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
/**
* #return the createdBy
*/
public String getCreatedBy() {
return createdBy;
}
/**
* #param createdBy the createdBy to set
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
/**
* #return the lastModifiedBy
*/
public String getLastModifiedBy() {
return lastModifiedBy;
}
/**
* #param lastModifiedBy the lastModifiedBy to set
*/
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
CommonDomainAttributes other = (CommonDomainAttributes) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("CommonDomainAttributes [id=").append(id)
.append(", createDate=").append(createDate)
.append(", lastModifiedDate=").append(lastModifiedDate)
.append(", createdBy=").append(createdBy)
.append(", lastModifiedBy=").append(lastModifiedBy)
.append(", toString()=").append(super.toString()).append("]");
return builder.toString();
}
}
public class Message extends CommonDomainAttributes implements Serializable{
private String fromuserId;
private String fromuserName;
private String toUserId;
private String touserName;
private String message;
/**
* #return the fromuserId
*/
public String getFromuserId() {
return fromuserId;
}
/**
* #param fromuserId the fromuserId to set
*/
public void setFromuserId(String fromuserId) {
this.fromuserId = fromuserId;
}
/**
* #return the fromuserName
*/
public String getFromuserName() {
return fromuserName;
}
/**
* #param fromuserName the fromuserName to set
*/
public void setFromuserName(String fromuserName) {
this.fromuserName = fromuserName;
}
/**
* #return the toUserId
*/
public String getToUserId() {
return toUserId;
}
/**
* #param toUserId the toUserId to set
*/
public void setToUserId(String toUserId) {
this.toUserId = toUserId;
}
/**
* #return the touserName
*/
public String getTouserName() {
return touserName;
}
/**
* #param touserName the touserName to set
*/
public void setTouserName(String touserName) {
this.touserName = touserName;
}
/**
* #return the message
*/
public String getMessage() {
return message;
}
/**
* #param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Message [fromuserId=");
builder.append(fromuserId);
builder.append(", fromuserName=");
builder.append(fromuserName);
builder.append(", toUserId=");
builder.append(toUserId);
builder.append(", touserName=");
builder.append(touserName);
builder.append(", message=");
builder.append(message);
builder.append(", toString()=");
builder.append(super.toString());
builder.append("]");
return builder.toString();
}
}
#Document(collection="discussion")
#TypeAlias("discussion")
public class Discussion extends CommonDomainAttributes implements Serializable{
private String discussionTopic;
private List<Message> messages;
/**
* #return the discussionTopic
*/
public String getDiscussionTopic() {
return discussionTopic;
}
/**
* #param discussionTopic the discussionTopic to set
*/
public void setDiscussionTopic(String discussionTopic) {
this.discussionTopic = discussionTopic;
}
/**
* #return the messages
*/
public List<Message> getMessages() {
return messages;
}
/**
* #param messages the messages to set
*/
public void setMessages(List<Message> messages) {
this.messages = messages;
}
/**
* #param messages the messages to set
*/
public void addMessages(Message message) {
if(null == messages){
messages = new LinkedList<>();
}
messages.add(message);
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Discussion [discussionTopic=");
builder.append(discussionTopic);
builder.append(", messages=");
builder.append(messages);
builder.append(", toString()=");
builder.append(super.toString());
builder.append("]");
return builder.toString();
}
}
A bit on Mongo Query Language
In MongoDB, the $slice operator controls the number of items of an array that a query returns. The $slice operator can accept values with following syntax:
[toSkip, toLimit]
Where the first value indicates the number of items in the array to skip and the second value indicates the number of items to return. For example, you can use the following query:
db.discussions.find({}, {messages: {$slice: [20, 10]}})
To return 10 messages, after skipping the first 20 messages of that array.
Bring it to Spring Data World
In order to use $slice operator with Spring Data MongoDB, you should use #Query annotation and its fields attribute. For example, if you have a DiscussionRepository, you could write something like:
public interface DiscussionRepository extends MongoRepository<Discussion, String> {
#Query(value = "{}", fields = "{messages: {$slice: [?0, ?1]}}")
List<Discussion> findDiscussions(int skip, int limit);
}
With this arrangement, following method call:
discussionRepository.findDiscussions(20, 10)
Would generate the same result as:
db.discussions.find({}, {messages: {$slice: [20, 10]}})
With a little bit of work, you can turn the Skip/Limit combination to a pagination functionality.

How does hibernate decide update/save associated objects

Anyone could help me explain about hibernate. How do it save/update child objects when we save/update parent object. Especially, Child Object with #EmbeddedId look like my mapping
#Embeddable
public class BomLevelKey implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
Item item;
long organizationId;
Item componentItem;
#Column(name = "organization_id")
public long getOrganizationId() {
return organizationId;
}
public void setOrganizationId(long organizationId) {
this.organizationId = organizationId;
}
#ManyToOne
#JoinColumn(name = "inventory_item_id")
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
#ManyToOne
#JoinColumn(name = "component_item_id")
public Item getComponentItem() {
return componentItem;
}
public void setComponentItem(Item componentItem) {
this.componentItem = componentItem;
}
#Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof BomLevelKey)) {
return false;
}
BomLevelKey key = (BomLevelKey) obj;
if (key.getItem().getInventoryItemID() == this.getItem()
.getInventoryItemID()
&& key.getComponentItem().getInventoryItemID() == this
.getComponentItem().getInventoryItemID()
&& key.getOrganizationId() == this.getOrganizationId()) {
return true;
}
return false;
}
}
#Entity
#Table(name = "es_bom_levels", schema = "xx_vms")
public class ItemConversionAttributes implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Double componentRoutingYield;
private Double forwardRoutingYield;
private Double conversionFactor;
private Double cumulativeLeadTime;
private Integer organizationID;
private Item componentItem;
private BomLevelKey id;
#EmbeddedId
public BomLevelKey getId() {
return id;
}
public void setId(BomLevelKey id) {
this.id = id;
}
/**
* #hibernate.property
* column="component_routing_yield"
*
**/
#Column(name="component_routing_yield")
public Double getComponentRoutingYield(){ return componentRoutingYield; }
public void setComponentRoutingYield(Double componentRoutingYield){ this.componentRoutingYield= componentRoutingYield; }
/**
* #hibernate.property
* column="forward_routing_yield"
*
**/
#Column(name="forward_routing_yield")
public Double getForwardRoutingYield(){ return forwardRoutingYield; }
public void setForwardRoutingYield(Double forwardRoutingYield){ this.forwardRoutingYield = forwardRoutingYield; }
/**
* #hibernate.property
* column="conversion_factor"
*
**/
#Column(name="conversion_factor")
public Double getConversionFactor(){ return conversionFactor; }
public void setConversionFactor(Double conversionFactor){ this.conversionFactor = conversionFactor; }
/**
* #hibernate.property
* column="cumulative_lead_time"
*
**/
#Column(name="cumulative_lead_time")
public Double getCumulativeLeadTime(){ return cumulativeLeadTime; }
public void setCumulativeLeadTime(Double cumulativeLeadTime){ this.cumulativeLeadTime = cumulativeLeadTime; }
/**
* #hibernate.property
* column="organization_id"
*
**/
#Column(name="organization_id", insertable = false, updatable = false)
public Integer getOrganizationID(){ return organizationID; }
public void setOrganizationID(Integer organizationID){ this.organizationID = organizationID; }
/**
* #hibernate.many-to-one
* column="component_item_id"
* insert="false"
* update="false"
*
**/
#ManyToOne(targetEntity=Item.class)
#JoinColumn(name="component_item_id", insertable=false, updatable=false)
#NotFound(action=NotFoundAction.IGNORE)
public Item getComponentItem(){ return componentItem; }
public void setComponentItem(Item componentItem){ this.componentItem = componentItem; }
}
In class Item, I've this mapping:
#OneToMany(mappedBy = "id.item")
#MapKey(name = "id.componentItem")
public Map<Item, ItemConversionAttributes> getConversionAttributes(){ return conversionAttributes; }
public void setConversionAttributes(Map<Item, ItemConversionAttributes> conversionAttributes) {
this.conversionAttributes = conversionAttributes;
}
save/update do nothing.
Its based on DAO Objects primary key's value.
If its set default value , hibernate will add otherwise update

There are multiple properties indexed against the same field name ..., but with different indexing settings. The behaviour is undefined

Getting the following in my log when I run my Hibernate Search application:
WARN 23 Jun 2014 15:08:51,623 org.hibernate.search.engine.metadata.impl.TypeMetadata:339 - HSEARCH000120: There are multiple properties indexed against the same field name 'foo.bar', but with different indexing settings. The behaviour is undefined.
I see that the warning is being logged from:
private Map<String, DocumentFieldMetadata> keyFieldMetadata(Set<PropertyMetadata> propertyMetadataSet) {
Map<String, DocumentFieldMetadata> tmpMap = new HashMap<String, DocumentFieldMetadata>();
for ( PropertyMetadata propertyMetadata : propertyMetadataSet ) {
for ( DocumentFieldMetadata documentFieldMetadata : propertyMetadata.getFieldMetadata() ) {
DocumentFieldMetadata oldFieldMetadata = tmpMap.put(
documentFieldMetadata.getName(),
documentFieldMetadata
);
if ( oldFieldMetadata != null ) {
if ( !documentFieldMetadata.getIndex().equals( oldFieldMetadata.getIndex() ) ) {
**log.inconsistentFieldConfiguration( documentFieldMetadata.getName()** );
}
}
}
}
for ( DocumentFieldMetadata documentFieldMetadata : classBridgeFields ) {
tmpMap.put( documentFieldMetadata.getName(), documentFieldMetadata );
}
if ( idPropertyMetadata != null ) {
for ( DocumentFieldMetadata documentFieldMetadata : idPropertyMetadata.getFieldMetadata() ) {
tmpMap.put( documentFieldMetadata.getName(), documentFieldMetadata );
}
}
return Collections.unmodifiableMap( tmpMap );
}
but I'm having trouble figuring out the purpose of this code, or how my code could be causing it to meet the condition. It appears to only be happening on fields annotated with #IndexedEmbedded I've Googled and found nothing for the error.
I assume that this has always been an issue in the code, but I just recently updated from Hibernate Search 4.2.0.Final to 4.5.1.Final, and this is when the warning began to appear.
UPDATE
#Entity
#Table(name = "data_providers")
#Immutable
#Embeddable
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class EDataProvider {
private static final long serialVersionUID = -4207808146855081627L;
public static final String FIELD_ASSOCIATIONS = "associations.";
public static final String FIELD_ID = "id";
private List<EDataProvider> associatedProviders;
private Long id;
private boolean isInternal;
private String name;
private Float priority;
public EDataProvider() {
this(null, null);
}
/**
* #param name
* #param id
*/
public EDataProvider(final String name, final Long id) {
super();
this.name = name;
this.id = id;
associatedProviders = new Vector<EDataProvider>();
}
/**
* #param newProvider
*/
public void addAssociatedProvider(final EDataProvider newProvider) {
associatedProviders.add(newProvider);
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if ((obj == null) || !(obj instanceof EDataProvider)) {
return false;
}
final EDataProvider other = (EDataProvider) obj;
if (!ObjectUtil.equals(getId(), other.getId())) {
return false;
}
return true;
}
#ManyToMany(fetch = FetchType.LAZY,
cascade = { CascadeType.PERSIST, CascadeType.MERGE })
#JoinTable(name = "data_provider_associations",
joinColumns = { #JoinColumn(name = "parent_id") },
inverseJoinColumns = { #JoinColumn(name = "child_id") })
#IndexedEmbedded(depth = 1,
prefix = FIELD_ASSOCIATIONS)
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public List<EDataProvider> getAssociatedProviders() {
return associatedProviders;
}
#Id
#Column(name = "id")
#Field(name = FIELD_ID)
public Long getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#Column(name = "boost")
public Float getPriority() {
return priority;
}
#Override
public int hashCode() {
return EncodingUtil.makeHashCode(31, getId());
}
#Column(name = "internal")
public boolean isInternal() {
return isInternal;
}
public void removeAssociatedProvider(final EDataProvider newProvider) {
associatedProviders.remove(newProvider);
}
/**
* #param newAssociatedProviders
* the associatedProviders to set
*/
public void setAssociatedProviders(
final List<EDataProvider> newAssociatedProviders) {
associatedProviders = newAssociatedProviders;
}
/**
* #param dataProviderId
* the dataProviderId to set
*/
public void setId(final Long dataProviderId) {
id = dataProviderId;
}
public void setInternal(final boolean isInternal) {
this.isInternal = isInternal;
}
/**
* #param name
* the name to set
*/
public void setName(final String name) {
this.name = name;
}
/**
* #param priority
* the priority to set
*/
public void setPriority(final Float priority) {
this.priority = priority;
}
#Override
public String toString() {
return String.format("provider:{id:%d, name:%s, priority:%f}", id, name,
priority);
}
}
The ID field was annotated in the child object with a #Field annotation as well as included in the parent object's index. The parent object uses a custom analyzer, so there was a conflict in the indexing settings. As soon as I removed the #Field annotation from the child object, the errors went away.

Hibernate error reading data from database

I have created an application using Spring MVC 3, Hibernate and Ext Js 4. The problem is that when I start the application the data is not readed from the database.
BookController.java:
#Controller
public class BookController {
private BookService bookService;
#RequestMapping(value="/books/view.action")
public #ResponseBody Map<String,? extends Object> view(#RequestParam int start, #RequestParam int limit) throws Exception {
try{
List<Book> books = bookService.getBookList(start,limit);
int total = bookService.getTotalBooks();
return ExtJSReturn.mapOK(books, total);
} catch (Exception e) {
return ExtJSReturn.mapError("Error retrieving books from database.");
}
}
BookService.java:
#Service
public class BookService {
private BookDAO bookDAO;
/**
* Get all books
* #return
*/
#Transactional(readOnly=true)
public List<Book> getBookList(int start, int limit){
return bookDAO.getBooks(start, limit);
}
public int getTotalBooks(){
return bookDAO.getTotalBooks();
}
BookDAO.java:
#SuppressWarnings("unchecked")
public List<Book> getBooks(int start, int limit) {
DetachedCriteria criteria = DetachedCriteria.forClass(Book.class);
return hibernateTemplate.findByCriteria(criteria, start, limit);
}
public int getTotalBooks(){
return DataAccessUtils.intResult(hibernateTemplate.find("SELECT COUNT(*) FROM books"));
}
Book.java:
#JsonAutoDetect
#Entity
#Table(name="books")
public class Book {
#Id
#GeneratedValue
#Column(name="id")
private int id;
#Column(name="title", nullable=false)
private String title;
#Column(name="author", nullable=false)
private String author;
#Column(name="publisher", nullable=false)
private String publisher;
#Column(name="isbn", nullable=false)
private String isbn;
#Column(name="pages", nullable=false)
private int pages;
#Column(name="category", nullable=false)
private String category;
#Column(name="qty", nullable=false)
private int qty;
/**
* #return the title
*/
public String getTitle() {
return title;
}
/**
* #param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* #return the author
*/
public String getAuthor() {
return author;
}
/**
* #param author the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* #return the publisher
*/
public String getPublisher() {
return publisher;
}
/**
* #param publisher the publisher to set
*/
public void setPublisher(String publisher) {
this.publisher = publisher;
}
/**
* #return the isbn
*/
public String getIsbn() {
return isbn;
}
/**
* #param isbn the isbn to set
*/
public void setIsbn(String isbn) {
this.isbn = isbn;
}
/**
* #return the pages
*/
public int getPages() {
return pages;
}
/**
* #param pages the pages to set
*/
public void setPages(int pages) {
this.pages = pages;
}
/**
* #return the category
*/
public String getCategory() {
return category;
}
/**
* #param category the category to set
*/
public void setCategory(String category) {
this.category = category;
}
/**
* #return the qty
*/
public int getQty() {
return qty;
}
/**
* #param qty the qty to set
*/
public void setQty(int qty) {
this.qty = qty;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
}
ExtJsReturn.java:
#Component
public class ExtJSReturn {
/**
* Generates modelMap to return in the modelAndView
* #param books
* #return
*/
public static Map<String,Object> mapOK(List<Book> books){
Map<String,Object> modelMap = new HashMap<String,Object>(3);
modelMap.put("total", books.size());
modelMap.put("data", books);
modelMap.put("success", true);
return modelMap;
}
/**
* Generates modelMap to return in the modelAndView
* #param books
* #return
*/
public static Map<String,Object> mapOK(List<Book> books, int total){
Map<String,Object> modelMap = new HashMap<String,Object>(3);
modelMap.put("total", total);
modelMap.put("data", books);
modelMap.put("success", true);
return modelMap;
}
/**
* Generates modelMap to return in the modelAndView in case
* of exception
* #param msg message
* #return
*/
public static Map<String,Object> mapError(String msg){
Map<String,Object> modelMap = new HashMap<String,Object>(2);
modelMap.put("message", msg);
modelMap.put("success", false);
return modelMap;
}
}
The error is raised from the controller: Error retrieving books from database.
Do you have any ideea what can be the problem?
See here the Console output: http://pastebin.com/jMQKS31P
FIXED!!!
https://stackoverflow.com/a/14447201/1564840
You're passing a SQL request, using tables and column names, to a method which expects an HQL request, using entities, mapped fields and associations. SQL and HQL are two different query languages.
The HQL query should be
select count(book.id) from Book book
If you don't know about HQL, then you really need to read the documentation. Using Hibernate without knowing HQL is like using JDBC without knowing SQL.

#ManyToMany association isn't inserted in the second table

I want to insert data into a table that is associated with another table in a relationship ManyToMany. When I insert the data, it is inserted into the table but the association with the other data that is in the second table is not. This is a Java EE application using JSF2+Spring+Hibernate.
Here is the entity:
#Entity
#Table(name="USER")
public class User {
private int id;
private String nom;
private Set<Formation> mesformations;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "USER_ID")
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the nom
*/
#Column(name="NOM",length=50)
public String getNOM() {
return nom;
}
/**
* #param nom the nom to set
*/
public void setNom(String nom) {
this.nom = nom;
}
/**
* #return the mesFormations
*/
#ManyToMany
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
#JoinTable(name = "USER_FORM",
joinColumns = #JoinColumn(name = "user_id",
referencedColumnName = "USER_ID"),
inverseJoinColumns = #JoinColumn(name = "form_id", referencedColumnName = "ID"))
public Set<Formation> getMesFormations() {
return mesFormations;
}
/**
* #param mesFormations the mesFormations to set
*/
public void setMesFormations(Set<Formation> mesFormations) {
this.mesFormations = mesFormations;
}
public void addToFormation(Formation formation) {
if(mesFormation==null)
{
mesFormations=new HashSet<Formation>();
}
mesFormations.add(formation);
}
.....
}
Formation.java
#Entity
#Table(name="Foramtion")
public class Formation {
private int id;
private String nomFormation;
private int nombreMatiere;
private Set<User> mesUsers;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the mesUsers
*/
#ManyToMany(mappedBy = "mesFormations",fetch=FetchType.LAZY)
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
public Set<User> getMesUsers() {
return mesUsers;
}
/**
* #param mesUsers the mesUsers to set
*/
public void setMesUsers(Set<User> mesUsers) {
this. mesUsers = mesUsers;
}
/**
* #return the nomFormation
*/
#Column(name="NOM_FORMATION",length=50,unique=true)
public String getNomFormation() {
return nomForamtion;
}
/**
* #param nomFormation the nomForamtion to set
*/
public void setNomForamtion(String nomForamtion) {
this.nomForamtion = nomForamtion;
}
/**
* #return the nombreMatiere
*/
public int getNombreMatiere() {
return nombreMatiere;
}
/**
* #param nombreMatiere the nombreMatiere to set
*/
public void setNombreMatiere(int nombreMatiere) {
this.nombreMatiere = nombreMatiere;
}
public void addToUser(User user) {
if(mesUser==null)
{
mesUsers=new HashSet<User>();
}
mesUsers.add(user);
user.addToFormation(this);
}
public void removeFromUser(User user) {
this.getMesUsers().remove(user);
user.getMesUsers().remove(this);
}
}
the method of the DAO layer which allows for the persistence of a user
public User enregistrer(User user) {
// TODO Auto-generated method stub
this.getSession().beginTransaction();
this.getSession().persist(user);
this.getSession().beginTransaction().commit();
return Entity ;
}
the method of the service layer that allows to call the save method of the dao layer
public User persistUser(User user, List<Integer> idList){
for(Integer id : idList){
Formation form = iformationDao.findById(id);
form.addToUser(user);
}
return iuserDao.enregistrer(user);
thank for answering
It looks to me like you have your CascadeTypes set to:
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
yet you are calling:
this.getSession().persist(user);
I think you will need to add CascadeType.PERSIST to your #Cascade annotation to get the behavior you desire.
change from
public User enregistrer(User user) {
// TODO Auto-generated method stub
this.getSession().beginTransaction();
this.getSession().persist(user);
this.getSession().beginTransaction().commit();
return Entity ;
}
to
public User enregistrer(User user) {
// TODO Auto-generated method stub
Transaction tx = this.getSession().beginTransaction();//change
this.getSession().persist(user);
tx.commit();//change
return Entity ;
}

Categories

Resources