I'm working on online exam project using struts spring and hibernate. While submitting the values from registration.jsp, i'm trying to insert those details in two different tables by using one table's primary key as foreign key in another table. But i could able to save only values in one table( says primary key table). But i could not able to save details in another table. In console log, i could see the follwing exception,
2013-09-17 18:16:39 INFO RegistrationAction:188 - Entering Into SaveUserDetails()
2013-09-17 18:16:39 INFO class:25 - Entering Into saveUserRegistration()
2013-09-17 18:16:39 INFO class:13 - Entering Into UserRegistrationDAO
Hibernate: insert into user_details (first_name, last_name, email, password, gender, dob, phone, experience) values (?, ?, ?, ?, ?, ?, ?, ?)
2013-09-17 18:16:39 INFO RegistrationAction:214 - Entering Into setUserAddress()
2013-09-17 18:16:39 INFO class:25 - Entering Into saveUserRegistration()
2013-09-17 18:16:39 INFO class:13 - Entering Into UserRegistrationDAO
2013-09-17 18:16:39 ERROR BasicPropertyAccessor:167 - IllegalArgumentException in class: onlineexam.beans.UserDetails, getter method of property: user_id
Sep 17, 2013 6:16:39 PM org.apache.catalina.core.ApplicationDispatcher invoke
RegistrationAction.java
public String SaveUserDetails() {
String forward = "success";
try {
logger.info("Entering Into SaveUserDetails()");//Log Information
UserDetails s = new UserDetails();
s.setFirst_name(getFirst_Name());
s.setLast_name(getLast_Name());
s.setEmail(getEmailid());
s.setPassword(getPassWord());
s.setGender(getGender());
s.setDob(getDateofbirth());
s.setPhone(getPhoneNo());
s.setExperience(getUser_experience());
userRegistrationService.saveUserRegistration(s);
Set<UserAddress> address = new HashSet<UserAddress>(0);
setUserAddress(address);
logger.info("SuccessFull:Exiting from SaveUserDetails()");//Log Information
} catch (Exception ex) {
forward = "error";
}
return forward;
}
public void setUserAddress(Set<UserAddress> address) throws Exception {
logger.info("Entering Into setUserAddress()");
UserAddress ad = new UserAddress();
ad.setAddr_line1(getAddr_line1());
ad.setAddr_line2(getAddr_line2());
ad.setAddr_line3(getAddr_line3());
ad.setCity(getCity());
ad.setZipcode(getZipcode());
ad.setState(getState());
ad.setCountry(getCountry());
address.add(ad);
userRegistrationService.saveUserRegistration(ad);
logger.info("SuccessFull:Exiting from setUserAddress()");//Log Information
}
}
UserRegistrationDAO.java
public class UserRegistrationDao extends HibernateDaoSupport {
private static Logger logger = Logger.getLogger("UserRegistrationDao.class");
public UserRegistrationDao() {}
public UserDetails saveUserRegistration(UserDetails s) throws Exception {
logger.info("Entering Into UserRegistrationDAO");
return (UserDetails)getHibernateTemplate().merge(s);
}
}
UserRegistrationService.java
public class UserRegistrationService {
private UserRegistrationDao userRegistrationDao;
private static Logger logger=Logger.getLogger("UserRegistrationService.class");
public void init() throws Exception {}
public UserRegistrationDao getUserRegistrationDao() {
logger.info("Entering into getUserRegistrationDao()");//Log information
return userRegistrationDao;
}
public void setUserRegistrationDao(UserRegistrationDao userRegistrationDao) {
this.userRegistrationDao = userRegistrationDao;
logger.info("Entering Into setUserRegistrationDao()");//Log Information
}
public UserDetails saveUserRegistration (UserDetails user) throws Exception {
logger.info("Entering Into saveUserRegistration()");//Log Information
return userRegistrationDao.saveUserRegistration(user);
}
}
UserDetails.java
public class UserDetails {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#OneToMany (mappedBy="user_details")
private int user_id; //primary key
private String first_name;
private String last_name;
private String email;
private String password;
private String gender;
private int dob;
private int phone;
private float experience;
//getters and setters created
UserAddress.java
public class UserAddress extends UserDetails {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int address_id; //primary key
#ManyToOne(fetch=FetchType.EAGER, targetEntity=UserDetails.class)
#JoinColumn(name="user_id")
private int user_id;
private String addr_line1;
private String addr_line2;
private String addr_line3;
private String city;
private int zipcode;
private String state;
private String country;
//getters and setters created
What are you doing in UserAddress doesn't constitute a many to one association from UserAddress to UserDetails. Your are only adding the user_id to UserDetails class.
What you have to do instead:
#ManyToOne(fetch=FetchType.EAGER, targetEntity=UserDetails.class)
#JoinColumn(name="user_id")
UserDetails userDetails;
public UserDetails getUserDetails() {
return userDetails;
}
public void setUserDetails() {
this.userDetails = userDetails;
}
I don't understand why UserAddress extends UserDetails? I recommend you to read more about hibernate associations.
Related
I have a problem trying to delete, then save a user in an application using the PostgreSQL database. Here is my controller:
#PostMapping
public String addCalories(#RequestParam Integer consumedKcal, HttpServletRequest request){
User u = (User) request.getSession().getAttribute("u");
User newUser = this.userService.save(u.getUsername(), u.getPassword(), u.getAge(), u.getGender(), u.getHeight(), u.getWeight(), u.getGoal(), u.getActivity_rate(), u.getKcal_needed(), u.getBmi(), consumedKcal);
return "redirect:/home";
}
Here is my service method:
#Override
#Transactional
public User save(String username, String password, Integer age, String gender, Float height, Float weight, String goal, String activity_rate, Integer kcal_needed, Float bmi, Integer kcal_consumed) {
this.userRepository.deleteUserByUsername(username);
User u = new User(username, password, age, gender, height, weight, goal, activity_rate, kcal_needed, bmi, kcal_consumed);
return this.userRepository.save(u);
}
The repository:
public interface UserRepository extends JpaRepository<User, Integer> {
User findUserByUsername(String username);
void deleteUserByUsername(String username);
}
The entity:
#Data
#Entity
#Table(name = "user_app")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer username_id;
private String username;
private String password;
private Integer age;
private String gender;
private Float height;
private Float weight;
private String goal;
private String activity_rate;
private Integer kcal_needed;
private Float bmi;
private Integer kcal_consumed;
private Integer water_consumed;
}
The JPA method delete works fine, it deletes the user. But I get this error duplicate key value violates unique constraint "user_username_key" Detail: Key (username)=(test) already exists. I don't know how to solve it. Any help is welcome.
If the createdBy references to a document with unique indexes, it fails throwing dup key error.
AbstractDocument.java
public abstract class AbstractDocument implements Auditable<User, String> {
#Version
private Long version;
#Id
private String id;
private User createdBy;
private DateTime createdDate;
private User lastModifiedBy;
private DateTime lastModifiedDate;
}
User.java
#Document(collection = "users")
public class User extends AbstractDocument {
private String name;
private String surname;
#Indexed(unique = true)
private String username;
}
Book.java
#Document(collection = "books")
public Book extends AbstractDocument {
private String title;
}
Now, I have a script (Spring Batch) which initializes the db with some books. The script defines the auditor this way:
#Configuration
#EnableMongoAuditing
public class MongoConfig {
#Bean
public AuditorAware<User> auditorProvider() {
return new AuditorAware<User>() {
#Override
public User getCurrentAuditor() {
User auditor = new User();
auditor.setUsername("init-batch");
auditor.setName("Data initializer");
auditor.setSurname("Data initializer");
return auditor;
}
};
}
}
The script in somewhere does (for each book I need to persist) bookRepository.save(book)
The first book is persisted, but the second one throws:
nested exception is com.mongodb.DuplicateKeyException: Write failed with error code 11000 and error message 'E11000 duplicate key error index: mydb.books.$createdBy.username dup key: { : "init-batch" }'
Why? The unique index is for users collection, why is it checked for audit references?
I am using Spring-data-mongodb and i can persist an object on a list, but when i try to add another, it doesn't work, the application doesn't throw an exception.
this is my Json:
[
{
idUser: "4a9f10d9-e19f-42af-ba00-891a567cc41f",
login: "peter",
password: "mypassword",
email: "peter#eeee.com",
patients:
[
{
idPatient: "d31e8052-36d3-4285-9f97-454f3437812d",
name: "ada",
birthday: 1363474800000,
idUser: "4a9f10d9-e19f-42af-ba00-891a567cc41f",
region:
{
idRegion: "d8acfa45-486e-49e0-b4e6-edde6743cf30",
name: "Madrid"
},
personalCalendars: null
},
null
]
}
]
As you can see, my first Patient element is correctly, and the second was insert as null.
I leave my code:
User.java
#Document(collection = "users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String id;
#Indexed
private UUID idUser;
#Indexed(unique = true)
private String login;
private String password;
#Indexed(unique = true)
private String email;
#DBRef
private List<Patient> patients;
#PersistenceConstructor
public User(UUID idUser, String login, String password, String email, List<Patient> patients){
this.idUser = idUser;
this.login = login;
this.password = password;
this.email = email;
this.patients = patients;
}
Patient.java
#Document(collection = "patients")
public class Patient implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String id;
#Indexed
private UUID idPatient;
private String name;
private Date birthday;
private UUID idUser;
private Region region;
#Transient
private List<PersonalCalendar> personalCalendars;
#PersistenceConstructor
public Patient(UUID idPatient, String name, Date birthday,UUID idUser, Region region){
this.idPatient = idPatient;
this.name = name;
this.birthday = birthday;
this.idUser = idUser;
this.region = region;
}
and the DAO whereI do the insert.
#Override
public Patient createPatient(User user, Patient patient) {
this.mongoOps.save(patient , "patients");
this.mongoOps.save(user , "users");
return this.getPatientById(patient.getIdPatient());
}
The console returns this, but no persists the patient:
15:16:16.718 [tomcat-http--6] DEBUG o.s.data.mongodb.core.MongoTemplate - Saving DBObject containing fields: [_class, _id, idPatient, name, birthday, idUser, region]
15:16:16.723 [tomcat-http--6] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[application]
15:16:16.747 [tomcat-http--6] DEBUG org.mongodb.driver.protocol.insert - Inserting 1 documents into namespace application.patients on connection [connectionId{localValue:2, serverValue:119}] to server 127.0.0.1:27017
15:16:16.761 [tomcat-http--6] DEBUG org.mongodb.driver.protocol.insert - Insert completed
I need help.
Thanks a lot
First, if you use Spring Data with MongoDB, use it properly:
#Repository
public interface UserRepository extends MongoRepository<User, String> {
}
Now just inject UserRepository via #Autowired annotation:
#Autowired
private UserRepository userRepository;
User user = new User();
Patient patient = new Patient();
user.addPatient(patient);
// Just call save from userRepository to save your User with Patient.
// save method will return instance of saved user (together with instance of
// patient)
User user = userRepository.save(user);
Note that save method can also be used for updating of existing User. If User is new (not having generated id) it will be inserted. If user exists (has generated id) it will be just updated.
Presuming that User class has a addPatient method that looks like this:
public void addPatient(Patient patient) {
this.patients.add(patient);
}
Also, make sure that your list is initialized: List<Patient> patients = new ArrayList<>();
I'm working on a project which is an assignment in a course I'm taking in the university.
In this project we are to implement an online forum system in a few iterations.
One of the requirements in this iteration is using ORM - we chose Hibernate and it's the first time we are experiencing it. so far we had a rough time :)
We're using intelliJ Idea 14, windows, java 7, mysql 5 and hibernate 4.2.
Among many classes we have POJOs that represent the domain layer and we have hibernateUtils which encapsulates the access to the DB, And a Junit class for testing it.
These are the annotated POJOs:
User:
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue
#Column(name="user_id")
private int id;
#Column(name="name")
private String username;
#Column(name="email_address")
private String emailAddress;
#Column(name="password")
private String hashedPassword;
#Column(name="date")
#Temporal(TemporalType.DATE)
private java.util.Date creationDate;
#OneToOne
#JoinColumn(name="state")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private UserState state;
#Column(name="is_active")
private boolean active;
#Column(name="is_banned")
private boolean banned;
#Column(name="is_logged_in")
private boolean loggedIn;
#ManyToMany
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private Set<User> friends;
#OneToMany
#JoinColumn(name="panding_notfications")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<Notification> pendingNotifications;
#OneToMany( mappedBy = "receivingMember")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<FriendRequest> friendRequests;
#OneToMany( mappedBy = "reporter")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<Report> sentReports;
#Column(name="seniority")
private int seniority;
#Column(name="loginTime")
private long loginTime;
Forum:
#Entity
#Table(name="Forum")
public class Forum {
#Id
#GeneratedValue
#Column(name="forum_id", nullable = false, unique = true)
public int id;
#Column(name="name")
private String name;
#OneToOne
#JoinColumn(name = "admin")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private User admin;
#OneToMany
#JoinColumn(name="sub_forums")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<SubForum> subForums;
#OneToMany
#JoinColumn(name="members")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<User> members;
#OneToOne
#JoinColumn(name="policy")
#Cascade({org.hibernate.annotations.CascadeType.ALL})
private ForumPolicy policy;
HibernateUtils:
public class HibernateUtils {
private static Configuration cfg;
private static SessionFactory sessionFactory =null;
public static boolean configure(boolean init) {
cfg = new Configuration()
.addAnnotatedClass(Forum.class)
.addAnnotatedClass(Message.class)
.addAnnotatedClass(SubForum.class)
.addAnnotatedClass(Thread.class)
.addAnnotatedClass(ForumPolicy.class)
.addAnnotatedClass(User.class)
.addAnnotatedClass(Report.class)
.addAnnotatedClass(Notification.class)
.addAnnotatedClass(FriendRequest.class)
.addAnnotatedClass(UserState.class)
.addAnnotatedClass(UserStatusPolicy.class)
.setProperty("hibernate.current_session_context_class","thread")
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect")
.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver")
.setProperty("hibernate.connection.url","jdbc:mysql://localhost:3306/forum_system")
.setProperty("hibernate.connection.username","root")
.setProperty("hibernate.password", "");
if (init) {
cfg.setProperty("hibernate.hbm2ddl.auto", "create");
}
sessionFactory = cfg.configure().buildSessionFactory();
return cfg!=null;
}
public synchronized static boolean start() {
return configure(false);
}
public static boolean init() {
return configure(true);
}
public synchronized static boolean save(Object o) {
return saveReturnId(o) > 0;
}
public synchronized static int saveReturnId(Object o) {
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
int id= (int)session.save(o);
session.getTransaction().commit();
return id;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return -1;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
public synchronized static boolean del(Object o) {
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
session.delete(o);
session.getTransaction().commit();
return true;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return false;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
public synchronized static Object load(Class c,int id) {
Object o=null;
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
o=session.get(c, id);
session.getTransaction().commit();
return o;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return null;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
}
The part of the test class that we are currently running:
public class ForumTests {
#BeforeClass
public static void Setup() {
HibernateUtils.start();
}
#Test
public void testSaveForum() {
Forum f = new Forum(new User(),new ForumPolicy(),"forum_name");
int id = HibernateUtils.saveReturnId(f);
Assert.assertEquals(f, (Forum) HibernateUtils.load(Forum.class, id));
}
#Test
public void testGetAdmin() {
User u =User.newMember("asdsad","asd","sdkfdjk#sldkf.com");
Forum f = new Forum(u,new ForumPolicy(),"forum_name");
int fid = HibernateUtils.saveReturnId(f);
Forum ormf = (Forum) HibernateUtils.load(Forum.class, fid);
Assert.assertEquals(u, ormf.getAdmin());
}
#Test
public void testAddSubforumFromForum() {
User u =User.newMember("user","pass","mail#gmail.com");
int uid = (int)HibernateUtils.saveReturnId(u);
Assert.assertTrue(uid>0);
/* commented out code */
}
When running each of the following tests separately they all succeed. But when running all of them we get this error: (In testGetAdmin test)
May 27, 2015 2:11:43 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1452, SQLState: 23000
May 27, 2015 2:11:43 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Cannot add or update a child row: a foreign key constraint fails (`forum_system`.`forum`, CONSTRAINT `FK_l9pbqj2i36itiuhbu7q61xqlq` FOREIGN KEY (`admin`) REFERENCES `user` (`user_id`))
org.hibernate.exception.ConstraintViolationException: could not execute statement
which I pretty much understand but i can't figure out why should that happen only when running all tests together? (maybe something about transactions?)
Thanks :)
Your tests are stateful, i.e. they are changing the data and leaving it changed after they run.
That means that when the next test runs, the data isn't "clean" but has been poluted by the tests before it.
To fix this, make sure the individual tests clean up after themselves OR set up a clean environment before each test runs - At present you initialise hibernate once for the whole class
My DB contain User table with same named fields in class User.
I still have a problem with #Column annotation: Intellij IDEA stresses the name of the column.
DBTable
CREATE TABLE "user"
(
email character varying,
login character varying NOT NULL,
password character varying NOT NULL,
name character varying NOT NULL,
id_user numeric NOT NULL,
CONSTRAINT user_pkey PRIMARY KEY (login, password, id_user),
CONSTRAINT user_email_key UNIQUE (email)
)
Why this exception of syntax?? I have the same named table
root cause
org.postgresql.util.PSQLException: ERROR: syntax error at or near "User"
Position: 13
org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:365)
org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133)
org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:58)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3067)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3509)
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:286)
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
com.classes.UserDB.registerUser(UserDB.java:17)
com.servlets.Registration.doPost(Registration.java:29)
javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
User class
package com.DB;
import javax.persistence.*;
#Entity
public class User {
#Lob
private String email;
#Lob
private String login;
#Lob
private String password;
#Lob
private String name;
#Id
#GeneratedValue
private int id_user;
public int getId_user() {
return id_user;
}
public void setId_user(int id_user) {
this.id_user = id_user;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getUserFromBase(){
return this;
}
}
How it resolve?
user is a reserved word and table with name user can not be created.
try adding #Table(name="USER_TABLE") after #Entity to change table name.
sorry haven`t read that carefully. it seems u already have a table named "USER". that's the problem with oracle
"user" is a reserved word in PostgreSQL and it's usually not a good idea use reserved words for tables or columns.
If you want to save yourself a lot of trouble use a different name. users, user_acount.
also would change the class name for the same as table.
put #Table(name="USERS") annotation:
#Entity
#Table(name="users")
public class Users {
}