I'm trying to create a #OneToMany relationship in the same entity. Here is a sample code:
#Entity
public class Client extends Model{
private static final long serialVersionUID = 1L;
public Client(String username, String email) {
super();
this.username = username;
this.email = email;
}
#Id
String username;
#Required
String email;
#ManyToOne
Client parent;
#OneToMany(mappedBy="parent")
Set<Client> friends = new HashSet<Client>();
static Finder<String,Client> find = new Finder<String,Client>(String.class, Client.class);
public static void create(Client regUser){
regUser.save();
}
public static Client getByUsername(String username){
return find.byId(username);
}
public void addFriend(Client relatedClient){
this.friends.add(relatedClient);
relatedClient.update();
this.update();
}
/**
* #return the username
*/
public String getUsername() {
return username;
}
/**
* #param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* #return the email
*/
public String getEmail() {
return email;
}
/**
* #param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* #return the friends
*/
public Set<Client> getFriends() {
return friends;
}
/**
* #param friends the friends to set
*/
public void setFriends(Set<Client> friends) {
this.friends = friends;
}
/**
* #return the parent
*/
public Client getParent() {
return parent;
}
/**
* #param parent the parent to set
*/
public void setParent(Client parent) {
this.parent = parent;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "Client [username=" + username + ", email=" + email + "]";
}
}
The problem is that after adding a new friend to a Client and searching for the same Client by Id, the friend list isn't updated correctly.
I tried your entity in an existing project I have setup, and it seems to work fine for me. I'm using play 2.1.1 with java 1.7, and Scala 2.10.0. There is this issue with enhancement that could be causing your issue.
Related
I have a view with many fields as query filters, and I am using JPA derived queries , however creating all queries for every combination of fields/filters would be tedious and long.
I found out that I can create a dynamic query for it, but not sure how.
So far I have created these queries in my repository, but still need a lot more :
public interface EmployeeReportInfoViewRepository extends PagingAndSortingRepository<EmployeeReportInfo, Long> {
List<EmployeeReportInfo> findByControlNumber(String controlNmber);
List<EmployeeReportInfo> findByManager(String manager);
List<EmployeeReportInfo> findByofficeLocation(String officeLocation);
List<EmployeeReportInfo> findByBenchFlag(char benchFlag);
List<EmployeeReportInfo> findByBillableFlag(char billableFlag);
List<EmployeeReportInfo> findByEnableFlag(boolean enableFlag);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumber(String lastName, String firstName,String controlNumber);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumberAndManager(String lastName, String firstName,String controlNmber,String manager);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumberAndManagerAndOfficeLocation(String lastName, String firstName,String controlNmber,String manager,String officeLocation);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumberAndManagerAndOfficeLocationAndBenchFlag(String lastName, String firstName,String controlNmber,String manager,String officeLocation, char benchFlag);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumberAndManagerAndOfficeLocationAndBenchFlagAndBillableFlag(String lastName, String firstName,String controlNmber,String manager,String officeLocation, char benchFlag,char bllableFlag);
List<EmployeeReportInfo> findByLastNameAndFirstNameAndControlNumberAndManagerAndOfficeLocationAndBenchFlagAndBillableFlagAndEnableFlagAndStartGreaterThanEqualAndEndLessThanEqual
(String lastName, String firstName,String controlNmber,String manager,String officeLocation, char benchFlag,char bllableFlag,
boolean emableFlag, Date start,Date end);
}
#Entity
#Table(name = "employee_report_view")
public class EmployeeReportInfo {
#Id
#Column(name = "employee_id")
private Long id;
private String name;
private Date start;
private Date end;
#Column(name = "control_number")
private String controlNumber;
#Column(name = "enable_flag")
private boolean enableFlag;
#Column(name = "billable_flag")
private char billableFlag;
#Column(name = "bench_flag")
private char benchFlag;
#Column(name = "office_location")
private String officeLocation;
#Column(name = "manager")
private String manager;
/**
* #return the id
*/
public Long getId() {
return id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the start
*/
public Date getStart() {
return start;
}
/**
* #param start the start to set
*/
public void setStart(Date start) {
this.start = start;
}
/**
* #return the end
*/
public Date getEnd() {
return end;
}
/**
* #param end the end to set
*/
public void setEnd(Date end) {
this.end = end;
}
/**
* #return the controlNumber
*/
public String getControlNumber() {
return controlNumber;
}
/**
* #param controlNumber the controlNumber to set
*/
public void setControlNumber(String controlNumber) {
this.controlNumber = controlNumber;
}
/**
* #return the enableFlag
*/
public boolean isEnableFlag() {
return enableFlag;
}
/**
* #param enableFlag the enableFlag to set
*/
public void setEnableFlag(boolean enableFlag) {
this.enableFlag = enableFlag;
}
/**
* #return the billableFlag
*/
public char getBillableFlag() {
return billableFlag;
}
/**
* #param billableFlag the billableFlag to set
*/
public void setBillableFlag(char billableFlag) {
this.billableFlag = billableFlag;
}
/**
* #return the benchFlag
*/
public char getBenchFlag() {
return benchFlag;
}
/**
* #param benchFlag the benchFlag to set
*/
public void setBenchFlag(char benchFlag) {
this.benchFlag = benchFlag;
}
/**
* #return the officeLocation
*/
public String getOfficeLocation() {
return officeLocation;
}
/**
* #param officeLocation the officeLocation to set
*/
public void setOfficeLocation(String officeLocation) {
this.officeLocation = officeLocation;
}
/**
* #return the manager
*/
public String getManager() {
return manager;
}
/**
* #param manager the manager to set
*/
public void setManager(String manager) {
this.manager = manager;
}
}
I can understand your needs:you want to dynamically generate query conditions based on the url issued by the form.Let's assume that the url maps to the back end to a HashMap<String,String>.
For instance,url:
127.0.0.1/employees?nameContains=jack&ageEquals=10
Map:
HashMap<String, String>:key:nameContains,value:jack,key:ageEuqals,value:10
The Spring framework can do this mapping automatically(RequestParamMapMethodArgumentResolver). What you need to do is to dynamically generate the Specification(Specification) by this map.
Gets the type of property corresponding to the field using reflect : name=>String, age=>Integer
Using CriteriaBuilder to build query criteria,it has comprehensive api,such as:
Predicate like(Expression x, String pattern); => contains
Predicate equal(Expression x, Expression y); => equal
Assemble your query criteria(or,and)
You get a Specification.
This is a relatively complex solution idea, which requires the coordination between the front table component and the back end, but it will be very convenient.
What I said is relatively simple and general, there are a lot of details.(such as nested properties,one-to-one,one-to-many,etc)
Also,You can have a look http://www.querydsl.com/
I have 25+ tables and I have used Content Provider with Database.
I have created separate files for each tables with following structure:
TProductUnit.java in package of com.myapp.db.tables
public class TProductUnit {
/***
* Fields of TABLE_PRODUCT_UNIT Table
***/
public static final String TABLE_PRODUCT_UNIT = "product_unit";
/**
* Columns of TABLE_PRODUCT_UNIT
*/
public static final String PRODUCT_UNIT_SERVER_ID = "id";
public static final String PRODUCT_UNIT_NAME = "name";
public static final String PRODUCT_UNIT_ITP = "itp";
public static final String PRODUCT_UNIT_UTP = "utp";
public static final String PRODUCT_UNIT_STATUS = "status";
public static String[] PRODUCT_UNIT_COLUMNS = new String[] {
BaseColumns._ID,
PRODUCT_UNIT_SERVER_ID,
PRODUCT_UNIT_NAME,
PRODUCT_UNIT_ITP,
PRODUCT_UNIT_UTP,
PRODUCT_UNIT_STATUS
};
}
ProductUnit.java is POJO class which will helpful when First time get data from Server.
public class ProductUnit {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("product_id")
#Expose
private Integer productId;
#SerializedName("url")
#Expose
private String url;
#SerializedName("bit")
#Expose
private int bit;
#SerializedName("status")
#Expose
private Integer status;
#SerializedName("itp")
#Expose
private String itp;
#SerializedName("utp")
#Expose
private String utp;
/**
* #return The id
*/
public Integer getId() {
return id;
}
/**
* #param id The id
*/
public void setId(Integer id) {
this.id = id;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public int getBit() {
return bit;
}
public void setBit(int bit) {
this.bit = bit;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
/**
* #return The status
*/
public Integer getStatus() {
return status;
}
/**
* #param status The status
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* #return The itp
*/
public String getItp() {
return itp;
}
/**
* #param itp The itp
*/
public void setItp(String itp) {
this.itp = itp;
}
/**
* #return The utp
*/
public String getUtp() {
return utp;
}
/**
* #param utp The utp
*/
public void setUtp(String utp) {
this.utp = utp;
}
/**
* Convenient method to get the objects data members in ContentValues object.
* This will be useful for Content Provider operations,
* which use ContentValues object to represent the data.
*
* #return
*/
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
values.put(PRODUCT_UNIT_SERVER_ID, id);
values.put(PRODUCT_UNIT_NAME, name);
values.put(PRODUCT_UNIT_ITP, itp);
values.put(PRODUCT_UNIT_UTP, utp);
values.put(PRODUCT_UNIT_STATUS, status);
return values;
}
}
Both classes have most of the same number of fields with same values if we think about #SerializedName
Problem:
Whenever I need to add some fields in any Particular Table then I have to add in all Table file and JSON POJO Class too.
When any field name changed by server side then I have to change in both file.
My Question is: Is there any better solution for this optimization. Have you ever manage like this?
P.S. I have 25+ tables so I have to create 50+ classes.
Help please. Thanks.
I have been trying hibernate-core-4.3.10.Final.jar to create a dummy project. I have created model class UserDetails which have one Address field which is in fact an embeddable object. In model class I have declared this field with #Embedded annotation but I haven't defined Address class as Embeddable using #Embeddable annotation. Still the object is being embedded in the UserDeatils entity. Is #Embeddable annotation optional?? Is #Embedded annotation sufficient for hibernate to do the mapping accordingly?
Following are the code snippets:-
/** UserDetails Class **/
package com.st.hibernate.models;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
#Entity
#Table(name="USER_DETAILS")
public class UserDetails {
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="USER_NAME")
#Transient
private String userName;
#Embedded
private Address address;
/**
* #return the address
*/
public Address getAddress() {
return address;
}
/**
* #param address the address to set
*/
public void setAddress(Address address) {
this.address = address;
}
#Temporal(TemporalType.DATE)
private Date currentDate;
#Lob // Large Objects----> CLob/BLob---->Character/Byte Larger Object
private String description;
/**
* #return the description
*/
public String getDescription() {
return description;
}
/**
* #param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* #return the currentDate
*/
public Date getCurrentDate() {
return currentDate;
}
/**
* #param currentDate the currentDate to set
*/
public void setCurrentDate(Date currentDate) {
this.currentDate = currentDate;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the userName
*/
public String getUserName() {
return userName;
}
/**
* #param userName the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}
}
and Address Class:-
package com.st.hibernate.models;
public class Address {
private String pincode;
private String city;
private String state;
/**
* #return the pincode
*/
public String getPincode() {
return pincode;
}
/**
* #param pincode the pincode to set
*/
public void setPincode(String pincode) {
this.pincode = pincode;
}
/**
* #return the city
*/
public String getCity() {
return city;
}
/**
* #param city the city to set
*/
public void setCity(String city) {
this.city = city;
}
/**
* #return the state
*/
public String getState() {
return state;
}
/**
* #param state the state to set
*/
public void setState(String state) {
this.state = state;
}
}
Thanks in advance.
My DTO is being stored using JPA Hibernate and I'm able to store the other fields but having trouble trying to store this relationship for the user. The userRoleSet HashSet has ENUMs that represent what roles that user has. Some users with have no roles while someone will have 1 to 3 roles. Each role is different. How would I got about representing this in my database and using JPA? At the moment, the #ManyToMany doesn't work, I miss be missing something else? Essentially, I need to be able to query that specific user in the database and have it return the roles that is assigned to that user.
UserType Enums
public enum UserType
{
ALPHA,BRAVO,CHARLIE
}
Default User DTO JPA
#Entity
#Table(name = "users")
public class DefaultUser implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private long user_id;
#Column(name = "user_name")
private String user_name;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "password")
private String password;
#ManyToMany
private Set<UserType> userRoleSet = new HashSet<UserType>();
/**
* #return the userTypes
*/
public Set<UserType> getUserTypes()
{
return userRoleSet;
}
/**
*
* #param userTypes
* the userTypes to set
*/
public void setUserTypes(Set<UserType> userTypes)
{
this.userRoleSet = userTypes;
}
/**
* #return the user_id
*/
public long getUser_id()
{
return user_id;
}
/**
* #return the user_name
*/
public String getUser_name()
{
return user_name;
}
/**
* #return the firstName
*/
public String getFirstName()
{
return firstName;
}
/**
* #return the lastName
*/
public String getLastName()
{
return lastName;
}
/**
* #return the password
*/
public String getPassword()
{
return password;
}
/**
* #param user_id
* the user_id to set
*/
public void setUser_id(long user_id)
{
this.user_id = user_id;
}
/**
* #param user_name
* the user_name to set
*/
public void setUser_name(String user_name)
{
this.user_name = user_name;
}
/**
* #param firstName
* the firstName to set
*/
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
/**
* #param lastName
* the lastName to set
*/
public void setLastName(String lastName)
{
this.lastName = lastName;
}
/**
* #param password
* the password to set
*/
public void setPassword(String password)
{
this.password = password;
}
}
The #ManyToMany annotation is used to map an association between two entities. For collections of simple types, the annotation to use is #ElementCollection.
PS: you always read and post the complete and exact error message you get when something "doesn't work".
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.