Here's my User:
package models.user;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import play.data.validation.Constraints.MaxLength;
import play.data.validation.Constraints.MinLength;
import play.data.validation.Constraints.Required;
import play.db.ebean.Model;
#Entity
#Table(name = "T_USER")
public class User extends Model {
#Id
public Long id;
#Required
#MaxLength(30)
#MinLength(4)
public String username;
#Required
#MaxLength(30)
#MinLength(4)
public String password;
#ManyToOne(fetch = FetchType.EAGER)
#Column(nullable = false)
public Role role;
public static Finder<Long, User> find = new Finder<Long, User>(Long.class, User.class);
public User() {
}
public User(String username, String password, Role role) {
this.username = username;
this.password = password;
this.role = role;
}
#Override
public String toString() {
return "[Tying to login : ] [" + username + " - " + password + "]";
}
}
In my controller, I want to get a user's role instance, so here's what I did:
public static Result modules(Long id) {
User user = User.find.byId(id);
if ("Super User".equalsIgnoreCase(user.role.name)) {
return ok();
} else {
return forbidden();
}
}
The problem is, user.role.name is null, but user.role.id is correct here, why EBean doesn't help me to fetch role for users ?
I have experienced this problem on different occasions. You could do the following:
First, try to replace your public fields with private ones and the add the appropriate getters and setters (this is a good pattern when using Java anyway).
Second, you can write a little helper for finding/fetching the needed information. So let's say you need to get the user by Id and the do this string check. Then in your User class you can write a method like this:
public static User findById(Long id) {
return Ebean.find(User.class)
.fetch("role")
.where()
.eq("id", id)
.findUnique();
}
After that, just use the method:
public static Result modules(Long id) {
User user = User.findById(id);
if ("Super User".equalsIgnoreCase(user.getRole().getName())) {
return ok();
} else {
return forbidden();
}
}
Related
I am using Spring Boot 4, Hibernate and JPA annotations. I ran into this error
org.hibernate.PersistentObjectException: detached entity passed to
persist.
I tried searching through the internet and couldn't quite get the proper answer. I tried to use merge instead of persist and it did not work. Besides I think merge is used when updating a resource.
Here is my code:
`
package com.matome.users.login.stats.springbootStarter.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.NamedQueries;
import com.matome.users.login.stats.springbootStarter.userconstants.UserRepositoryConstants;
#NamedQueries({
#NamedQuery(name = UserRepositoryConstants.NAME_GET_ALL_USERS,
query = UserRepositoryConstants.QUERY_GET_ALL_USERS),
#NamedQuery(name = UserRepositoryConstants.NAME_GET_USER_BY_ID,
query = UserRepositoryConstants.QUERY_GET_USER_BY_ID),
#NamedQuery(name = UserRepositoryConstants.NAME_GET_USER_BY_USERNAME,
query = UserRepositoryConstants.QUERY_GET_USER_BY_USERNAME),
#NamedQuery(name = UserRepositoryConstants.NAME_DELETE_USER,
query = UserRepositoryConstants.QUERY_DELETE_USER)
})
#Entity
public class User implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String username;
String password;
String phone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
`
CRUD service
`
package com.matome.users.login.stats.springbootStarter.CRUDService;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.repository.UserRepository;
#Service
#Transactional
public class UserCRUDService {
#Autowired
UserRepository userRepository;
public User createUser(User user) {
userRepository.save(user);
return user;
}
public User updateUser(User user) {
User existingUser = userRepository.getUserById(user.getId());
if (existingUser == null) {
throw new NoResultException();
}
existingUser.setId(user.getId());
existingUser.setUsername(user.getUsername());
existingUser.setPhone(user.getPhone());
existingUser.setPassword(user.getPassword());
userRepository.update(user);
return user;
}
public User deleteUser(long id) {
User user = userRepository.getUserById(id);
if (user == null) {
throw new NoResultException();
}
userRepository.delete(user);
return user;
}
}
`
Repository
`
package com.matome.users.login.stats.springbootStarter.repository;
import java.util.List;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.userconstants.UserRepositoryConstants;
#Repository
#Transactional
public class UserRepository extends AbstractRepository<User> {
TypedQuery<User> query;
public List<User> getAllUsers() {
query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_ALL_USERS, User.class);
return query.getResultList();
}
public User getUserById(long id) {
query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_USER_BY_ID, User.class);
query.setParameter("id", id);
return query.getSingleResult();
}
public User getUserByUsername(String username) {
query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_USER_BY_USERNAME, User.class);
query.setParameter("username", username);
return query.getSingleResult();
}
}
`
Abstract repository
`
package com.matome.users.login.stats.springbootStarter.repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public abstract class AbstractRepository<T> {
#PersistenceContext
protected EntityManager entityManager;
#Transactional(propagation = Propagation.MANDATORY)
public void save(T entity) {
entityManager.persist(entity);
entityManager.flush();
entityManager.refresh(entity);
}
#Transactional
public T update(T entity) {
return entityManager.merge(entity);
}
#Transactional
public void delete(T entity) {
entityManager.remove(entity);
}
}
`
Factory
`
package com.matome.users.login.stats.springbootStarter.factories;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.matome.users.login.stats.springbootStarter.BackingForm.UserBackingForm;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.viewmodels.UserViewModel;
#Service
public class UserFactory {
public UserViewModel createViewModel(User user) {
UserViewModel viewModel = new UserViewModel();
viewModel.setId(user.getId());
viewModel.setUsername(user.getUsername());
viewModel.setPhone(user.getPhone());
return viewModel;
}
public List<UserViewModel> createVewModels(List<User> users) {
List<UserViewModel> viewModels = new ArrayList<>();
if (users != null) {
for (User user : users) {
viewModels.add(createViewModel(user));
}
}
return viewModels;
}
public User createEntity(UserBackingForm userBackingForm) {
User user = new User();
user.setId(userBackingForm.getId());
user.setUsername(userBackingForm.getUsername());
user.setPassword(userBackingForm.getPassword());
user.setPhone(userBackingForm.getPhone());
return user;
}
}
`
Backing form
`
package com.matome.users.login.stats.springbootStarter.BackingForm;
public class UserBackingForm {
private long id;
private String username;
private String password;
private String phone;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
`
Controller
`
package com.matome.users.login.stats.springbootStarter.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.matome.users.login.stats.springbootStarter.BackingForm.UserBackingForm;
import com.matome.users.login.stats.springbootStarter.CRUDService.UserCRUDService;
import com.matome.users.login.stats.springbootStarter.factories.UserFactory;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.repository.UserRepository;
import com.matome.users.login.stats.springbootStarter.viewmodels.UserViewModel;
#RestController
#RequestMapping("api")
public class UserController {
#Autowired
private UserRepository userRepository;
#Autowired
private UserCRUDService userCRUDService;
#Autowired
private UserFactory userFactory;
#RequestMapping(value = "/users", method = RequestMethod.GET)
public Map<String, Object> getAllUsers() {
Map<String, Object> map = new HashMap<>();
map.put("users", userRepository.getAllUsers());
return map;
}
#RequestMapping(value = "{id}", method = RequestMethod.GET)
public Map<String, Object> getUserById(#PathVariable long id) {
Map<String, Object> map = new HashMap<>();
map.put("user", userRepository.getUserById(id));
return map;
}
#RequestMapping(value = "/user/add", method = RequestMethod.POST)
public UserViewModel addUser(#RequestBody UserBackingForm form) {
User user = userFactory.createEntity(form);
//user.setIsActive(true);
user = userCRUDService.createUser(user);
return userFactory.createViewModel(user);
}
#RequestMapping(value = "/user/add/{id}", method = RequestMethod.PUT)
public Map<String, Object> updateUser(#PathVariable("id") Long id, #RequestBody User user) {
Map<String, Object> map = new HashMap<>();
user.setId(id);
map.put("updatedUser", userCRUDService.updateUser(user));
return map;
}
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String testFinal() {
return "User test sucessfully";
}
#RequestMapping(value = "{id}", method = RequestMethod.DELETE)
public void deleteUser(#PathVariable("id") Long id) {
User user = userRepository.getUserById(id);
userRepository.delete(user);
}
}
`
View Model
`
package com.matome.users.login.stats.springbootStarter.viewmodels;
public class UserViewModel extends BaseViewModel<Long> {
private String username;
private String phone;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
`
base ViewModel
`
package com.matome.users.login.stats.springbootStarter.viewmodels;
public abstract class BaseViewModel<T> {
private T id;
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
#SuppressWarnings("unchecked")
BaseViewModel<T> other = (BaseViewModel<T>) obj;
if (getId() == null) {
if (other.getId() != null)
return false;
} else if (!getId().equals(other.getId()))
return false;
return true;
}
}
`
Main
`
package com.matome.users.login.stats.springbootStarter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Main { public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}
`
Stack Trace
`
org.hibernate.PersistentObjectException: detached entity passed to persist: com.matome.users.login.stats.springbootStarter.model.User
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at com.sun.proxy.$Proxy78.persist(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
`
In my opinion the problem lies in the fact that you have declared the id of User entity as auto-generated:
#Id #GeneratedValue(strategy = GenerationType.AUTO)
Long id;
and when you create the User object you set the id manually:
public User createEntity(UserBackingForm userBackingForm) {
User user = new User();
user.setId(userBackingForm.getId());
...
and thus when you pass that to persist / save, the Persistence Provider will not allow that as it expects that the id will not be set by the client.
The bottom line is that you should not set the id regarding the current configuration when you are aiming at persisting a new entry and you should be fine.
Can you provide a full stack trace ?
Some hints for you :
You should only set #Transactional at Service level, not dao / repository.
Entitymanager refresh method means get data from DB to recreate an entity. If you just persist the entity, there is no need to refresh it.
#Transactional(propagation = Propagation.MANDATORY)
public void save(T entity) {
entityManager.persist(entity);
entityManager.flush(); // This is not really usefull on a small transaction
entityManager.refresh(entity); // No need for that : persist means entity already in sync
}
On update side, if you have a managed entity there is no need to sync it back to the DB, JPA take care of that automatically. (and merge push entity in the db forcing an update of all column) :
public User updateUser(User user) {
User existingUser = userRepository.getUserById(user.getId());
// ...
existingUser.setPassword(user.getPassword());
// ...
userRepository.update(user); // This is not needed !
return user;
}
If you want simplest things, you should take a look at lombok. It will help you write simpliest bean ( #Data to generate getter/setter ...)
You use Spring, so take also a look at spring-Data-JPA, It writes for you some cumberstone code.
I am following the Spring tutorial to get started with JPA, and I have a basic mysql db with a user table.
I've set up User.java as follows:
package com.test.models;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Id;
import java.util.UUID;
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
#Column(name="id")
private UUID id;
#Column(name="first_name")
String first_name;
#Column(name="last_name")
String last_name;
#Column(name="username")
String username;
public User(String first_name, String last_name, String username) {
this.first_name = first_name;
this.last_name = last_name;
this.username = username;
}
public User() { }
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
I've set up the UserRepo.java:
package com.test.models;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.UUID;
#RepositoryRestResource
public interface UserRepo extends CrudRepository<User, UUID>{
User findByUsername(String username);
}
And finally the UserController.java:
package com.test.controllers;
import com.test.models.UserRepo;
import com.test.models.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class UserController {
#Autowired
private UserRepo userRepo;
#RequestMapping("/create")
#ResponseBody
public String create(String first_name, String last_name, String username) {
String userId = "";
try {
User user = new User(first_name, last_name, username);
userRepo.save(user);
userId = String.valueOf(user.getId());
}
catch (Exception ex) {
return "Error creating the user: " + ex.toString();
}
return "User successfully created with id = " + userId;
}
}
I've also set up my db connection:
spring.datasource.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=fakepass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
However, when I use postman to make a POST to localhost:8080/create with
{
"first_name": "Jim",
"last_name": "Smith",
"username": "jim.smith"
}
I get this error:
Error creating the user:
org.springframework.orm.jpa.JpaSystemException: Could not set field
value [ff80818158b79f8e0158b7a285b60001] value by reflection : [class
com.test.models.User.id] setter of com.test.models.User.id; nested
exception is org.hibernate.PropertyAccessException: Could not set
field value [ff80818158b79f8e0158b7a285b60001] value by reflection :
[class com.test.models.User.id] setter of com.test.models.User.id
I had the same problem. Your strategy in #GenericGenerator is set incorrectly.
Try:
#GenericGenerator(name = "system-uuid", strategy = "org.hibernate.id.UUIDGenerator")
All JPA entity classes should have the empty constructors and your User class is missing empty constructor which is causing this issue, so change your User Entity class as shown below and add User() constructor:
public class User {
public User() {//empty constructor
}
//add existing code here
}
The entity class must have a no-arg constructor. The entity class may
have other constructors as well. The no-arg constructor must be public
or protected.
You can look here for the spec.
in dataBase exists UUID type, try to use UUID instead of varchar(36).
I want to establish one to many relation between table vendor detail and product detail. like one vendor can have multiple products. but when i am inserting data into table its inserting all the four fields but not mapping vendorid into ProductDetail Table
and query generated is this.
Hibernate: insert into ProductInfo (productCategory, productDetails, productPrice, VendorId) values (?, ?, ?, ?) It shuld map vendor ID also but in table its empty.
VendorDetail.java
package com.cts.entity;
import javax.persistence.*;
#Entity
#Table(name = "VendorInfo")
public class VendorDetails {
#Id
#Column
private Long VendorId;
#OneToMany
private ProductDetails productdetail;
#Column
private String VendorName;
#Column
private String Password;
public String getVendorName() {
return VendorName;
}
public void setVendorName(String vendorName) {
VendorName = vendorName;
}
public Long getVendorId() {
return VendorId;
}
public void setVendorId(Long vendorId) {
VendorId = vendorId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
}
ProductDetails.java
package com.cts.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity#Table(name = "ProductInfo")
public class ProductDetails {
#ManyToOne(cascade = CascadeType.ALL)#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
public ProductDetails() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int productId;
#Column
private String productCategory;
#Column
private String productDetails;
#Column
private String productPrice;
public VendorDetails getVendordetails() {
return vendordetails;
}
public void setVendordetails(VendorDetails vendordetails) {
this.vendordetails = vendordetails;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getProductDetails() {
return productDetails;
}
public void setProductDetails(String productDetails) {
this.productDetails = productDetails;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
}
DAO class ProductDetailDaoImpl.java
package com.cts.Dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.cts.entity.ProductDetails;
import com.cts.entity.to.ProductDetailsTo;
#Repository
public class ProductDetailDaoImpl implements ProductDetailDao {
#Autowired
SessionFactory sessionFactory;
#Transactional
public boolean saveProductInfo(ProductDetailsTo productTo) {
System.out.println("M in Registration DAO");
System.out.println(productTo.getProductCategory());
System.out.println(productTo.getProductDetails());
System.out.println(productTo.getProductId());
System.out.println(productTo.getProductPrice());
//getting productTo data to entity class
ProductDetails prodet = productTo.getEntity();
System.out.println("Value of product details is:" + prodet.getProductDetails());
sessionFactory.getCurrentSession().save(prodet);
return false;
}
}
VendorDetails has many ProductDetails so you need to make one to many annotation like this:-
#OneToMany(mappedBy="vendordetails") //mappedBy value will be what you declared //in ProductDetails class.
private Collection<ProductDetails> productdetail=new ArrayList<ProductDetails>;
and create the setter and getter of this.
Now in ProductDetails class you need to annotate many to one like this:-
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
Then a new column named 'VendorId' will be create in table 'ProductInfo' and since declare mappedBy value="vendordetails" so each vendor id would be insert.
I think you should replace the code
#OneToMany
private ProductDetails productdetail;
to
#OneToMany
private Set productdetailSet;
And create setter and getter for this.
You can visit the blog http://gaurav1216.blogspot.in/2014/01/hibernate-tutorial-day-5.html for one to many using annotation.
I am attempting to create a Java application using Play 2.3 and the master snap-shot of securesocial that will allow users to login using either Facebook , Google+ or Twitter the allow users to link their accounts together and persist this information to a database . I have been having trouble writing a UserService (particularly when linking accounts) that will allow for this. I have found examples using earlier versions of Play/securesocial but have been unable to find an example using the master snap-shot.
If anyone has any examples they could share it would be appreciated.
I was able to create the UserService.
User Model
import play.db.ebean.Model;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Entity
#Table(name = "users")
public class User extends Model {
#Id
#GeneratedValue
public Long id;
public Date lastLogin;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
public List<Profile> identities;
public User(Profile profile){
identities = new ArrayList<Profile>();
this.identities.add(profile);
lastLogin = new Date();
}
public static Finder<String ,User> find = new Finder<String, User>(String.class, User.class);
}
Profile Model
import play.db.ebean.Model;
import securesocial.core.BasicProfile;
import javax.persistence.*;
#Entity
#Table(name = "profiles")
public class Profile extends Model {
#Id
#GeneratedValue
public Long id;
public String providerId;
public String authUserId;
public String firstName;
public String lastName;
public String fullName;
public String email;
public String avatarUrl;
#ManyToOne
#JoinColumn(name = "user_id")
public User user;
public Profile(BasicProfile profile){
this.providerId = profile.providerId();
this.authUserId = profile.userId();
if(profile.firstName().isDefined())
firstName = profile.firstName().get();
if(profile.lastName().isDefined())
lastName = profile.lastName().get();
if(profile.fullName().isDefined())
fullName = profile.fullName().get();
if(profile.email().isDefined())
email = profile.email().get();
if(profile.avatarUrl().isDefined())
avatarUrl = profile.avatarUrl().get();
}
}
And the User Service
package services;
import models.Profile;
import models.User;
import play.libs.F;
import securesocial.core.BasicProfile;
import securesocial.core.PasswordInfo;
import securesocial.core.java.BaseUserService;
import securesocial.core.java.Token;
import securesocial.core.services.SaveMode;
import java.util.Date;
import java.util.List;
public class DemoUserService extends BaseUserService<User> {
#Override
public F.Promise<User> doSave(BasicProfile basicProfile, SaveMode saveMode) {
User result = null;
if(saveMode == SaveMode.SignUp()){
Profile profile = new Profile(basicProfile);
result = new User(profile);
profile.user = result;
result.save();
}else if(saveMode == SaveMode.LoggedIn()){
List<User> users = User.find.all();
for(User user: users){
for(Profile p : user.identities) {
if (p.authUserId.equals(basicProfile.userId()) && p.providerId.equals(basicProfile.providerId())) {
result = user;
result.lastLogin = new Date();
result.update();
}
}
}
}else{
throw new RuntimeException("Unknown mode");
}
return F.Promise.pure(result);
}
#Override
public F.Promise<User> doLink(User user, BasicProfile basicProfile) {
User target;
User u = User.find.byId(user.id.toString());
if(u == null) {
throw new RuntimeException("Cant find user");
}
target = u;
boolean linked = false;
for(Profile p : target.identities){
if(p.authUserId.equals(basicProfile.userId()) && p.providerId.equals(basicProfile.providerId())){
linked = true;
}
}
if(!linked) {
target.identities.add(new Profile(basicProfile));
target.update();
}
return F.Promise.pure(target);
}
#Override
public F.Promise<BasicProfile> doFind(String providerId, String userId) {
BasicProfile found = null;
List<User> users = User.find.all();
for(User u: users){
for(Profile i : u.identities){
if(i.providerId.equals(providerId) && i.authUserId.equals(userId)){
found = new BasicProfile(providerId , userId , null , null , null , null , null , null , null , null , null);
break;
}
}
}
return F.Promise.pure(found);
}
#Override
public F.Promise<BasicProfile> doFindByEmailAndProvider(String s, String s1) {
return null;
}
#Override
public F.Promise<Token> doSaveToken(Token token) {
return null;
}
#Override
public F.Promise<Token> doDeleteToken(String s) {
return null;
}
#Override
public void doDeleteExpiredTokens() {
}
#Override
public F.Promise<Token> doFindToken(String s) {
return null;
}
#Override
public F.Promise<PasswordInfo> doPasswordInfoFor(User user) {
return null;
}
#Override
public F.Promise<BasicProfile> doUpdatePasswordInfo(User user, PasswordInfo passwordInfo) {
return null;
}
}
This is my annotation class and i want userId and groupId column both as primary key.
I have found more questions (Question) about this, but didn't found relevant answer.
I have less reputation, so I am not able to comment on posts, So I am putting my question here.
This is my code..
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.NaturalId;
#Entity
#Table(name="user_group")
public class user_group {
#Column(name="serviceProvider")
private String serviceProvider;
#Column(name="enterpriseId")
private String enterpriseId;
#Column(name="department")
private String department;
#Column(name="trunkGroupName")
private String trunkGroupName;
#Id
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getServiceProvider() {
return serviceProvider;
}
public void setServiceProvider(String serviceProvider) {
this.serviceProvider = serviceProvider;
}
public String getEnterpriseId() {
return enterpriseId;
}
public void setEnterpriseId(String enterpriseId) {
this.enterpriseId = enterpriseId;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getTrunkGroupName() {
return trunkGroupName;
}
public void setTrunkGroupName(String trunkGroupName) {
this.trunkGroupName = trunkGroupName;
}
}
You should create a new #Embeddable class containing the PK fields:
#Embeddable
public class user_groupId implements Serializable {
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
}
And use it in the #Entity as an #EmbeddedId:
#Entity
public class user_group {
#EmbeddedId
user_groupId id;
...
}
You could also use the #IdClass annotation to that effect.
This excellent answer by Pascal Thivent elaborates on the details. You can also take a look at this other answer I posted to a almost identical question some time ago.
As a side note, if you've got control over the DB structure, you might also consider avoiding composite keys. There are some reasons to do so.
you can create a composite primary key in hibernate using #UniqueConstraint annotation.
#Table(name="user_group",uniqueConstraints=#UniqueConstraint(columnNames= {"userId","groupId"}))
public class user_group
{
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
}
above method is not feasible if we use spring because for creating composite primary key we have to create a class is not a good thing.
in hibernate and spring you only have to create POJO classes which are available as an entity on your system.