after setting attribute for HttpSession it becomes Null - java

I'm developing a Sign up operation, where the user enter his email and password press the submit(createUser method) button, User entity get persisted AND set the id of User in HttpSession, next he moved to next jsf where enter information for School Object (Entity). My problem is that the User get persisted BUT the School is not. here is my code:
public CreateBn() {
user = new User();
school = new School();
adress = new Adresse();
school.setAdresse(adress);
facesContext = FacesContext.getCurrentInstance();
session = (HttpSession) facesContext.getExternalContext().getSession(false);
}
public String createUser() {
initialiserDateInscription();
session.setAttribute("UserId", user.getId());
//System.out.println((BigInteger) session.getAttribute("UserId"));
userPr.createUser(user);
return SHCOOL_INSCRIPTION;
}
public String createSchool() {
BigInteger userId = (BigInteger) session.getAttribute("UserId");
System.out.println("MEHDI : " + userId);
try {
User userTemp = userPr.getUserById(userId);// Here is the problem
school.setUser(userTemp);
} catch (Exception e) {
e.printStackTrace();
}
session.setAttribute("SchoolId", school.getId());
school.setAdresse(adress);
schoolPr.createSchool(school);
return INSCRIPTION_RETURN;
}
as you can see I get the User entity based on the UserId saved in session, but I get nothing, it says:
javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
any more info, I'm here. So how can I solve this??
#Entity
#Table(schema = "school", name = "school")
public class School implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private BigInteger id;
private String name;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "userId")
private User user;
#OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
#JoinColumn(name = "adressId")
private Adresse adresse;
EJB
#Stateless
public class UserPr {
#PersistenceContext(unitName = "proj")
private EntityManager em;
public void createUser(User user) throws RuntimeException{
try {
em.persist(user);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public User getUserById(BigInteger UserId) throws Exception{
try{
return em.createNamedQuery("User.findById", User.class).setParameter("id", UserId).getSingleResult();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
#NamedQueries({
#NamedQuery(name="User.findById", query="SELECT u FROM User u WHERE u.id = :id")
})
public class User implements Serializable {

Try changing the way you get and set the userId.
instead of this line
session.setAttribute("UserId", user.getId());
try this
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
Map<String, Object> sessionMap = externalContext.getSessionMap();
sessionMap.put("UserId", user.getId());
and instead of this
BigInteger userId = (BigInteger) session.getAttribute("UserId");
try this
BigInteger userId = (BigInteger) sessionMap.get("UserId");

First some remarks about the mode: I don't think School should have a OneToOne relationship with User. More likely it is a OneToMany relationship. And maybe you don't want to have a separate Entity for Adresse, it could probably be an Embeddable instead.
How is your persistence set up? How are you managing transactions? The problem you see might be caused by transactional boundaries. How are the createUser and createSchool methods called exactly?

Related

JPA: "Can't write; duplicate key in table" for a One-to-One relationship

I have these entities that I want to relate bi-directionaly.
Credential:
#Entity
#Access(AccessType.PROPERTY)
#Table(name = "credential")
public class Credential extends MetaInfo implements Serializable {
...
private Email email;
...
#OneToOne(cascade = CascadeType.ALL, optional = false, orphanRemoval = true)
#JoinColumn(name="email", referencedColumnName="email_address")
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
...
}
Email:
#Entity
#Access(AccessType.PROPERTY)
#Table(name = "email")
public class Email extends MetaInfo implements Serializable{
...
private Credential credential;
public Email() {
}
public Email(String emailAddress) {
this.emailAddress = emailAddress;
}
#Id
#Column(name="email_address")
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
#OneToOne(mappedBy = "email", optional=false)
public Credential getCredential() {
return credential;
}
public void setCredential(Credential credential) {
this.credential = credential;
}
}
In a CredentialRepository class I am testing whether the passed-in email
is not assigned to any user except for the user with the username passed-in as the second (optional) parameter:
#Override
public boolean emailIsAssigned(String... args) {
assert(args.length > 0);
if(InputValidators.isValidEmail.test(args[0])){
EntityManager em = entityManagerFactory.createEntityManager();
try {
TypedQuery<Long> count = em.createQuery("SELECT COUNT(e) "
+ "FROM Email e WHERE e.emailAddress "
+ "= :email AND e "
+ "IN (SELECT c.email FROM Credential c WHERE c.username "
+ "!= :username)", Long.TYPE).setParameter("email", args[0])
.setParameter("username", null);
if(InputValidators.stringNotNullNorEmpty.apply(args[1])){
//only if the username has been provided
count.setParameter("username", args[1]);
}
return count.getSingleResult() > 0;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
} finally {
em.close();
}
}else{
throw new NotAValidEmailException(args[0] + " is not a"
+ " valid email address.");
}
}
Thus above args[0] is the email under test and args[1] is the username under test.
And this is the test that is causing me problems (note that before I already successfully tested inserts, updates and even the emailIsAssigned method but without the c.email part which seems to cause the issue:
#Test
public void emailAlreadyExistsTest(){
assertTrue(credentialRepo.emailIsAssigned("existing_email#yahoo.ca"));
}
And this is the error message that I have:
[EL Warning]: 2017-04-17 17:55:33.606--ServerSession(234430897)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Can't write; duplicate key in table '#sql-3e4_9a'
Error Code: 1022
Call: ALTER TABLE credential ADD CONSTRAINT FK_credential_email FOREIGN KEY (email) REFERENCES email (email_address)
Query: DataModifyQuery(sql="ALTER TABLE credential ADD CONSTRAINT FK_credential_email FOREIGN KEY (email) REFERENCES email (email_address)")
I would appreciate if someone could give me a piece of advice. I could always just change the email into a String and mark it as "unique" in #Column, but I feel that there is no reason for the chosen approach not to work.
I am using MySQL as the DB vendor, and Eclipse-Link JPA implementation. I did try to "hard-change" the name of the FK constraint but to no avail. The DB and all tables have the same collation (utf8_unicode_ci).
Try to delete the primary key for class Email because "extends MetaInfo"

Need to save two tables from different jsp pages with foreign key relationship using hibernate dao implementation method

Image of table relationship reference
After submit from bank jsp page and after submit from card jsp all in one image because of limitation of newbie
I am new to stackoverflow as well SPRING. I have tried to create two tables with foreign key concept . I have followed some examples on stackoverflow as well as from other resourcefull websites and manged to create two tables with onetomany relationship. But the problem is i have to get the first row id under cart_id column when i submit from card jsp page. Instead after submit from card jsp page there is new row created under bankadmin table and it's id is being returned. I am confused and have no idea how to correct ot resolve this issue. Please be kind and guide me. And also i have been searching for a week in stackoverflow couldn't find anything that helped me. Thanks in advance.
Bankadmin Model
#Entity
#Table(name = "bankAdmin")
public class bankAdmin implements Serializable{
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "bcode", nullable=false)
#Id private int bcode;
#Column (name = "bname")
private String bname;
#Column (name = "address")
private String address;
#Column (name = "phno")
private int phno;
#OneToMany(mappedBy="bankAdmin",cascade = CascadeType.ALL)
private Set<Cards> cards;
Card model
#Entity
#Table(name = "cards")
public class Cards implements Serializable {
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="cname", unique=true)
#Id private int cname;
#Column (name = "ctype")
private String ctype;
#Column (name = "min_sal")
private int min_sal;
#Column (name = "year_fee")
private int year_fee;
#Column (name = "rewards")
private String rewards;
#Column (name = "jperks")
private String jperks;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="cart_id", nullable=false)
private bankAdmin bankAdmin;
public Cards(){}
public Cards(String ctype, int min_sal, int year_fee, String rewards, String jperks, bankAdmin b){//int cname,
this.ctype=ctype;
this.min_sal=min_sal;
this.year_fee=year_fee;
this.jperks=jperks;
this.rewards=rewards;
this.bankAdmin=b;
}
public bankAdmin getBankAdmin() {
return bankAdmin;
}
public void setBankAdmin(bankAdmin bankAdmin) {
this.bankAdmin = bankAdmin;
}
CardDaoImpl
public class CardsDaoImpl implements CardsDao{
#Autowired
SessionFactory sessionfactory;
public void save(Cards cards) {
Session session = null;
Transaction tx = null;
try
{
session = this.sessionfactory.openSession();
tx = session.beginTransaction();
bankAdmin bankadmin =new bankAdmin(); //=null;
String _ctype = cards.getctype();
int _min_sal = cards.getmin_sal();
int _year_fee = cards.getyear_fee();
String _rewards = cards.getrewards();
String _jperks = cards.getjperks();
Set<Cards> card = new HashSet<Cards>();
Cards config = new Cards(_ctype,_min_sal,_year_fee,_rewards,_jperks,bankadmin);
card.add(config);
bankadmin.setcards(card);
// System.out.println("bankadmin: before " + bankadmin);
// bankadmin.setbname(bankadmin.getbname());// "SBI"
// bankadmin.setphno(bankadmin.getphno());//1234567890
// bankadmin.setaddress(bankadmin.getaddress());//Bengaluru
// System.out.println("bankadmin: after " + bankadmin);
// int _cname = cards.getcname();
// int bankadmin = bankadmin.getbcode();
//_cname,_ctype,_min_sal,_year_fee,_rewards,_jperks,bankadmin
// card.add(config);
// config.setBankAdmin(cards.getBankAdmin(bankadmin));
// config.setcname(cards.getcname());
// config.setctype(cards.getctype());
// config.setmin_sal(cards.getmin_sal());
// config.setyear_fee(cards.getyear_fee());
// config.setrewards(cards.getrewards());
// config.setjperks(cards.getjperks());
// config.setBankAdmin(cards.getBankAdmin());
session.save(bankadmin);
session.save(config);
tx.commit();
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
session.close();
}
}
// get lms lights config from DB
public List<Cards> Ccards() {
Session session = null;
// Transaction tx = null;
List<Cards> Ccards = null;
try{
session = this.sessionfactory.openSession();
Ccards = session.createQuery("FROM Cards").list();
System.out.println("cards dao impl executed...");
System.out.println("cards config : "+ Ccards.toString());
}
catch (Exception e)
{
System.out.println("bankAdmin Dao impl Ex : " + e);
}
finally
{
session.close();
}
return Ccards;
}
}
BankDaoImpl
public class bankAdminDaoImpl implements bankAdminDao{
#Autowired
SessionFactory sessionfactory;
public void save(bankAdmin badmin) {
Session session = null;
Transaction tx = null;
try
{
session = this.sessionfactory.openSession();
tx = session.beginTransaction();
// bankAdmin bankadmin = new bankAdmin();
bankAdmin config = new bankAdmin();
config.setbcode(badmin.getbcode());
config.setbname(badmin.getbname());
config.setaddress(badmin.getaddress());
config.setphno(badmin.getphno());
session.save(config);//save//persist
tx.commit();
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
session.close();
}
}
// get lms lights config from DB
public List<bankAdmin> BbankAdmin() {
Session session = null;
// Transaction tx = null;
List<bankAdmin> BbankAdmin = null;
try{
session = this.sessionfactory.openSession();
BbankAdmin = session.createQuery("FROM bankAdmin").list();
System.out.println("bankAdmin dao impl executed...");
System.out.println("bankAdmin config : "+ BbankAdmin.toString());
}
catch (Exception e)
{
System.out.println("bankAdmin Dao impl Ex : " + e);
}
finally
{
session.close();
}
return BbankAdmin;
}
}
Okay. I have posted the solution to your problem.
First of all, Spring framework is wonderful to work with. The framework got a lot of features, that you should take advantage of. I am not sure if I will be able to cover everything in this post, so please feel free to ask me.
I have created a simple Spring Boot application. I got total of 6 files that are important which is posted below.
Notice that I renamed your classes to CamelCase with capital starting letter. such as BankAdmin. This is considered the standard way of writing java classes. Also note that i renamed Cards to Card, so remember to rename your table in the database aswell. Also remember to rename the bankadmin table to bank_admin.
There are thee annotations that you have to look into. #Transactional, #Autowired, and PersistenceContext.
So a quick and easy explanation. #Transactional manages all transactions for you, so you do not have to begin and commit transactions. #Autowired creates objects for you, so you do not have to manage your object dependencies yourself. PersistenceContext basically creates and EntityManager for you and manages it for you. You do not have to create session nor EntitManagerFactory. These three annotations are explained very brief, so you should read about them yourself.
I also removed #Table(name = "bankAdmin") and #Table(name = "cards"). JPA can lookup these tables automatically if you follow the standard way of naming classes and database tables. It is actually pretty simple, but I still encourage you to look into this by yourself. In short, capital camelcase is turned into lowercase with _ inbetween each word that start with a capital letter. I.e. If your class name is BankAdmin then JPA will automatically look for table named bank_admin in your database.
application.properties - details about your database
spring.datasource.url=jdbc:mysql://localhost:3306/stackoverflow?useSSL=false
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.show-sql = true
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto = update
The below code is only written to test the functionality
#SpringBootApplication
public class StackoverflowApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(StackoverflowApplication.class, args);
//Calling a class that is only made with the purpose of testing
Verification ts = ctx.getBean(Verification.class);
ts.run();
}
}
#Component
class Verification{
#Autowired
private BankAdminDao bad;
#Autowired
private CardsDao cd;
void run(){
//Create a new BankAdmin
BankAdmin ba = new BankAdmin();
ba.setAddress("someStreet");
ba.setPhno(12341234);
ba.setBname("myBanker");
//Create two cards and add them to a HashSet.
Card c1 = new Card("Visa", 1000, 1999, "Alot of", "Babes", ba);
Card c2 = new Card("Master Card", 2000, 500, "someThing", "anotherThing", ba);
Set<Card> cardList = new HashSet<>();
cardList.add(c1);
cardList.add(c2);
//Create a associatio between the BankAdmin and list of Cards
ba.setCards(cardList);
//Save them to the database.
bad.save(ba);
//Here we add a Card to an existing BankAdmin with the id 6 in the database.
//Create a new Card.
//The BankAdmin is set to null, because we not have not yet loaded the BankAdmin
Card c3 = new Card("Visa", 9999, 1337, "Alot of", "Male Babes", null);
//Save Card c3 with the BankAdmin id 6
cd.save(c3, 6);
}
}
BankAdmin
#Entity
public class BankAdmin implements Serializable{
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "bcode", nullable=false)
#Id private int bcode;
#Column (name = "bname")
private String bname;
#Column (name = "address")
private String address;
#Column (name = "phno")
private int phno;
#OneToMany(mappedBy="bankAdmin",cascade=CascadeType.ALL)
private Set<Card> cards;
//Getters and Setters have been removed to reduce the amount of code.
}
BankAdminDao
#Repository
//Transactional makes transaction automatical, so you do not have to begin and commit transactions yourself!
#Transactional
public class BankAdminDao{
//This makes your life a lot eaier!
//It will take care of your EntitManagerFactory and Sessions
#PersistenceContext
EntityManager em;
public void save(BankAdmin bank) {
em.merge(bank);
}
//get lms lights config from DB
public List<BankAdmin> getAllBankAdmin() {
List<BankAdmin> bankList = (List<BankAdmin>)em.createQuery("SELECT b FROM BankAdmin b");
return bankList;
}
public BankAdmin getBankAdmin(int bankId) {
return em.find(BankAdmin.class, bankId);
}
}
Card
#Entity
public class Card implements Serializable {
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="cname", unique=true)
#Id private int cname;
#Column (name = "ctype")
private String ctype;
#Column (name = "min_sal")
private int min_sal;
#Column (name = "year_fee")
private int year_fee;
#Column (name = "rewards")
private String rewards;
#Column (name = "jperks")
private String jperks;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="cart_id", nullable=false)
private BankAdmin bankAdmin;
public Card(){}
public Card(String ctype, int min_sal, int year_fee, String rewards, String jperks, BankAdmin b){
this.ctype=ctype;
this.min_sal=min_sal;
this.year_fee=year_fee;
this.jperks=jperks;
this.rewards=rewards;
this.bankAdmin=b;
}
public BankAdmin getBankAdmin() {
return bankAdmin;
}
public void setBankAdmin(BankAdmin bankAdmin) {
this.bankAdmin = bankAdmin;
}
}
CardDao
#Repository
#Transactional
public class CardsDao{
#PersistenceContext
EntityManager em;
#Autowired
BankAdminDao bad;
public void save(Card cards, int bankId) {
BankAdmin bank = bad.getBankAdmin(bankId);
cards.setBankAdmin(bank);
bank.getCards().add(cards);
em.merge(bank);
}
public List<Card> getAllCards() {
List<Card> cardList = (List<Card>)em.createQuery("SELECT c FROM Cards c");
return cardList;
}
public Card getCard(int cardId){
return em.find(Card.class, cardId);
}
}

Creating unique and merging existing row in database with JPA

I have 2 tables: User and Loan.
User have 3 fields: id (PK), first_name and last_name. Loan table have field user_id that is foreign key to User table:
By persisting a new Loan I need to create new User if his first_name and last_name are unique, otherwise put his id in uder_id.
The source code of my Loan class:
public class Loan {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long sum;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User user;
... methods ...
I'm using this method to persist new User:
#PersistenceContext
private EntityManager em;
public void save(User user) {
if (user.getId() == null) {
em.persist(user);
} else {
em.merge(user);
}
}
And when I try to save a new Loan it always persists a new User with the same first_name and last_name but different id.
loan.setSum(sum);
loan.setUser(new User(firstName, lastName));
loanService.save(loan);
To use user's first_name and last_name as a PK is not a solution, I need an id.
UPDATE_1
I tried to find User by his name:
public User findByName(String firstName, String lastName) {
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u WHERE u.firstName = :firstName " +
"AND u.lastName = :lastName", User.class)
.setParameter("firstName", firstName).setParameter("lastName", lastName);
return query.getSingleResult();
}
But when I enter new user I got an exception:
javax.faces.FacesException: #{loanBean.requestLoan()}: javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.
And when I enter existing user, it adds a new one with the same firstName and lastName but new id.
When I repeat this operation I got another exception:
javax.servlet.ServletException: javax.persistence.NonUniqueResultException: More than one result was returned from Query.getSingleResult()
UPDATE_2
Thanks a lot Pietro Boido for your really helpful suggestions.I created unique index on first_name and last_name fields in DB and refactor the save() method. But now when I enter existing user's data I got new exception
javax.servlet.ServletException: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'FIRST_LAST_NAME' defined on 'USER'.
Error Code: 20000
You should first execute a query to find the user by name and create a new one only if it was not found:
User user = userService.find(firstName, lastName);
if (user == null) {
user = loanService.createUser(new User(firstName, lastName));
}
loan.setSum(sum);
loan.setUser(user);
loanService.save(loan);
Since there might be no user with the given name, use getResultList when you query for the user, because getSingleResult expects to always find a result.
List<User> users = query.getResultList();
if (!users.isEmpty()) {
return users.iterator().next();
} else {
return null;
}
The code assumes that the database has a unique index on first_name, last_name.
You should not cascade operations on the ManyToOne relationship. Think about this: if you delete a loan, should the user be deleted too?
Cascading operations should be used when the related entity is part of the relating entity and their life cycles are managed together.
#Entity
#Table(name="loans")
public class Loan implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "total")
private Long sum;
#ManyToOne()
#JoinColumn(name = "user_id")
private User user;
//...
}
Here is a possible working example:
#Stateless
public class LoanService implements LoanServiceRemote {
#PersistenceContext
private EntityManager em;
#Override
public User createUser(User user) {
em.persist(user);
return user;
}
#Override
public Loan createLoan(Loan loan) {
em.persist(loan);
System.out.println("loan persisted: id=" + loan.getId());
return loan;
}
#Override
public Loan saveLoan(Loan loan) {
em.merge(loan);
return loan;
}
#Override
public Long incrementLoan(Integer loanId, long amount) {
Loan loan = em.find(Loan.class, loanId);
if (loan != null) {
long sum = loan.getSum() + amount;
/*
* The entity is bound to the entity manager,
* because it was returned by the find method.
* We can simply set its properties and
* the entity manager will update the datasource
* after the method returns and the transaction commits.
* No need to call persist or merge.
*/
loan.setSum(sum);
return sum;
}
return null;
}
#Override
public boolean deleteLoan(Integer loanId) {
Loan loan = em.find(Loan.class, loanId);
if (loan != null) {
em.remove(loan);
return true;
}
return false;
}
#Override
public Loan findLoan(Integer loanId) {
return em.find(Loan.class, loanId);
}
#Override
public List<Loan> requestLoans(LoanRequest loanRequest) {
User user;
TypedQuery<User> query = em.createQuery("select user from User user where user.firstName = :firstName and user.lastName = :lastName", User.class);
query.setParameter("firstName", loanRequest.getFirstName());
query.setParameter("lastName", loanRequest.getLastName());
List<User> users = query.getResultList();
if (users.isEmpty()) {
user = new User();
user.setFirstName(loanRequest.getFirstName());
user.setLastName(loanRequest.getLastName());
//new entities must be persisted
em.persist(user);
} else {
user = users.get(0);
}
List<Loan> loans = new ArrayList<>();
Long[] totals = loanRequest.getTotals();
for (int i = 0; i < totals.length; i++) {
Loan loan = new Loan();
loan.setSum(totals[i]);
loan.setUser(user);
em.persist(loan);
loans.add(loan);
}
return loans;
}
}
A unit test:
#Test
public void testLoan() {
User user = loanService.createUser(newUser());
Loan loan1 = new Loan();
loan1.setSum(10L);
loan1.setUser(user);
Loan loan2 = loanService.createLoan(loan1);
assertNotNull(loan2);
Integer loanId = loan2.getId();
assertNotNull(loanId);
assertEquals(loan1.getSum(), loan2.getSum());
assertEquals(loan1.getUser(), user);
User user2 = loanService.createUser(newUser());
loan2.setUser(user2);
loan2.setSum(20L);
Loan loan3 = loanService.saveLoan(loan2);
assertLoanEquals(loan2, loan3);
Long total = loanService.incrementLoan(loanId, 10L);
assertNotNull(total);
assertEquals((Long)(loan3.getSum() + 10L), total);
loan3.setSum(total);
Loan loan4 = loanService.findLoan(loanId);
assertLoanEquals(loan3, loan4);
boolean result = loanService.deleteLoan(loanId);
assertTrue(result);
Loan loan5 = loanService.findLoan(loanId);
assertNull(loan5);
Long[] totals = new Long[]{1L,2L,3L};
LoanRequest loanRequest = new LoanRequest();
loanRequest.setFirstName("Amerigo");
loanRequest.setLastName("Vespucci");
loanRequest.setTotals(totals);
List<Loan> loans = loanService.requestLoans(loanRequest);
assertNotNull(loans);
assertEquals(3, loans.size());
for (int i = 0; i < 3; i++) {
assertEquals(totals[i], loans.get(i).getSum());
loanService.deleteLoan(loans.get(i).getId());
}
}
void assertLoanEquals(Loan loan1, Loan loan2) {
assertNotNull(loan1);
assertNotNull(loan2);
assertEquals(loan1.getSum(), loan2.getSum());
assertUserEquals(loan1.getUser(), loan2.getUser());
assertEquals(loan1.getId(), loan2.getId());
}
void assertUserEquals(User user, User user2) {
assertNotNull(user);
assertNotNull(user2);
assertEquals(user.getId(), user2.getId());
assertEquals(user.getFirstName(), user2.getFirstName());
assertEquals(user.getLastName(), user2.getLastName());
}

Hibernate Model: set default #ManyToOne value of a Child Class

I have class User which has #ManyToOne field Role.
#Entity
#Table(name="USERS")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorValue("ROLE_ADMIN")
#DiscriminatorColumn (name="ROLENAME", discriminatorType= DiscriminatorType.STRING, length=20)
public class User extends BaseEntity implements UserDetails {
// all others fields like username, password,...
#ManyToOne
#JoinColumn(name = "role_id", referencedColumnName="id")
#NotNull(message = "ROLE field is mandatory")
private Role role;
//getter and setter
}
I have many classes that extends User: UserSeller, UserClient, UserOffice....
#Entity
#DiscriminatorValue("ROLE_SELLER")
#AttributeOverride(name = "role", column = #Column(name = "role_id"))
public class UserSeller extends User {
//additional fields like CompanyId,...
//getter & setter
}
I have one panel where i can insert / edit / delete all kind of users,
but i must have also "n" panel: one for each kind of user.
When i'm in these panel, i would like to be able to insert these UserSeller without having
to put a where to choose role, but i want set this role as default.
• I tried to put a costructor in the UserSeller
#Entity
#DiscriminatorValue("ROLE_SELLER")
#AttributeOverride(name = "role", column = #Column(name = "role_id"))
public class UserSeller extends User {
#Transient
RoleService roleService;
#Transient
User user = new User();
public UserSeller()
{
super();
try
{
this.setRole(roleService.getRole("ROLE_SELLER"));
}
catch (RecordNotFoundException e)
{
}
}
but i get this error:
Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
• i tried to pass a User object to constructor:
public UserSeller(User user)
and in controller i do this:
User user = new User();
UserSeller seller = new UserSeller(user);
model.addAttribute("seller", seller);
but i get this error:
No default constructor for entity: com.machinet.model.UserVenditore
If, in UserSeller i declare again the Role field i get error about
"Redefined Column"....
Finally i found this that i though could be my solution (in
UserSeller class):
#PrePersist
public void prePersist() {
try
{
this.setRole(roleService.getRole("ROLE_SELLER"));
}
catch (RecordNotFoundException e)
{
}
}
but when i'm in the UserSeller panel and i try to add a new Seller, it doesnt' take the default role and the validation fails.
I would like to know how can i do the trick: i want that my UserSeller, UserClient,... have a default value when i insert a new record.
Do i really need to do this in the controller? is this the only way? because for a beginner like me, it doesn't look so so elegant solution:
UserVenditore venditore = new UserVenditore();
try
{
venditore.setRole(roleService.getRole("ROLE_VENDITORE"));
}
catch (RecordNotFoundException ex)
{
}
model.addAttribute("venditore", venditore);
edit: also this last solution doesn't work: it fails the validation!
Thank you for any suggestion!
for now, i found only this solution (in the ControllerClass):
in removed #Valid before #ModelAttribute
i manually set the role
i manually validate the object
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addingSeller(#ModelAttribute UserSeller seller,
BindingResult result, RedirectAttributes redirectAttrs) {
logger.info("IN: Seller/add-POST");
//set role
try
{
seller.setRole(roleService.getRole("ROLE_SELLER"));
}
catch (RecordNotFoundException ex)
{
}
//validation
validator.validate(seller, result);
if (result.hasErrors()) {
logger.info("Seller-add error: " + result.toString());
redirectAttrs.addFlashAttribute("org.springframework.validation.BindingResult.seller", result);
redirectAttrs.addFlashAttribute("seller", seller);
} else {
try
{
SellerService.addSeller(seller);
//message to the user
String message = "Seller added!";
redirectAttrs.addFlashAttribute("message", message);
redirectAttrs.addFlashAttribute("message_class", "alert-success");
}
catch (DuplicateRecordException e)
{
//the username already exists
//message to the user
String message = "Already exists an user with this USERNAME";
redirectAttrs.addFlashAttribute("message", message);
redirectAttrs.addFlashAttribute("message_class", "alert-danger");
redirectAttrs.addFlashAttribute("seller", seller);
}
}
return "redirect:/sellers/list";
}

hibernate parent child relationship

Let's say I have entity A and entity B. Entity A have #OneTomany relationship with B.
I want to persist row in A only if it has one or more child object's associated with it else throw an exception.
How can i achieve the above requirement in hibernate
You neglected to mention what version of Hibernate you are using. In any case, this falls within the purview of validation. Luckily, in both Hibernate 3 and 4 you can utilize Hibernate Validator to do the job:
public class EntityB implements Serializable {
}
public class EntityA implements Serializable {
#NotNull
#Size(min = 1)
private Set<EntityB> relatedEntities;
}
You may need to pull in the Hibernate Validator jars into your project in order to be able to do this.
Entity class:Register.class
public class Register{
private Long regId;
#OneToMany(mappedBy = "reg")
private Set addrSet;
public Set getAddrSet() {
return addrSet;
}
public void setAddrSet(Set<Address> addrSet) {
this.addrSet = addrSet;
}
}
Entity Class:Address.java
public class Address{
object values;
#ManyToOne
private Register reg;
public Register getReg() {
return reg;
}
public void setReg(Register reg) {
this.reg = reg;
}
}
public void class searchObject(){
public List lst;
public register searchRegisterRow(Long regId){
Session session = null;
SessionFactory sessionFactory = null;
register result = null;
try{
sessionFactory = new Configuration().configure().buildSessionFactory();
session =sessionFactory.openSession();
String SQL_QUERY ="from Register r where r.redId = "+regId;
Register reg = session.createQuery(SQL_QUERY);
for(Iterator it=lst.iterator();it.hasNext();){
reg=(Register)it.next();
if(reg.getAddrSet().size() > 0){
result = reg;
}
else{
throw new Exception();
}
}
return result;
}
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
// Actual contact insertion will happen at this step
session.flush();
session.close();
}
}
}
I think you should try above code. this will help you.

Categories

Resources