I want to relate friends of users, the problem I have is how to get the friends of a user? I think part of my problem is that I am putting the list of friends as an attribute in the User class, private Set<User> friends = new HashSet<>();
is that ok?
I am putting this json through swagger
, since they are existing users in the database.
{
"friend": {
"email": "string",
"friends": [],
"id": 0,
"name": "string",
"password": "string"
},
"owner": {
"email": "wwww",
"friends": [],
"id": 3,
"name": "dsadsa",
"password": "d"
}
}
This is my controller, where everything starts:
@PostMapping("/addFriend")
public ResponseEntity<User> getUser(@RequestBody Friendship friendship) {
log.info("addFriend");
return new ResponseEntity<User>(userServiceImpl.createLinkWithFriends(friendship), HttpStatus.OK);
}
This is the service:
public User createLinkWithFriends(Friendship friendship) {
User owner=userRepository.findById(friendship.getOwner().getId());
User friend=userRepository.findById(friendship.getFriend().getId());
owner.addFriend(friend);
friendsRepository.save(friendship);
return owner;
}
and this is the repository User
@Entity
@Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = -3009157732242241606L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "email")
private String email;
@OneToMany(fetch=FetchType.EAGER)
@JoinTable(
name = "Friendship",
joinColumns = @JoinColumn(name = "id"),
inverseJoinColumns = @JoinColumn(name = "idFriend"))
private Set<User> friends = new HashSet<>();
public User() {
}
public User(String name, long id, String password, String email) {
this.email = email;
this.name = name;
this.id = id;
this.password = password;
}
public void addFriend(User userFriend){
this.friends.add(userFriend);
}
This is the Friendship class
@Entity
@Table(name = "Friendship")
public class Friendship implements Serializable {
private static final long serialVersionUID = -3009157732242241606L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long idFriend;
@ManyToOne
private User owner;
@ManyToOne
private User friend;
public Friendship() {
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public User getFriend() {
return friend;
}
public void setFriend(User friend) {
this.friend = friend;
}
}
i get this error when i do mvn clean package
2019-05-03 23:54:59.925 INFO 20200 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final}
2019-05-03 23:54:59.925 INFO 20200 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-05-03 23:54:59.931 INFO 20200 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist
2019-05-03 23:54:59.979 INFO 20200 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2019-05-03 23:55:00.132 INFO 20200 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2019-05-03 23:55:01.094 INFO 20200 --- [ main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update
2019-05-03 23:55:01.132 INFO 20200 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: friendship
2019-05-03 23:55:01.133 INFO 20200 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: friendship
2019-05-03 23:55:01.136 WARN 20200 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.sp
ringframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/Hibern
ateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFac
tory
2019-05-03 23:55:01.152 INFO 20200 --- [ main] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2019-05-03 23:55:01.184 ERROR 20200 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/
HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate Sess
ionFactory
I uploaded my project to github https://github.com/hubmanS/traslateInClick , I would really appreciate if you do the test
Regarding the error:
detached entity passed to persist: com.example.demo.model.User
And based on:
at com.example.demo.service.UserServiceImpl.createLinkWithFriends(UserServiceImpl.java:42)
It seems to me that the problem is that you are saving
friendship
as it came by parameter, and from what you see the objects that make it up are not from the persistence context but rather what has been deserialized in the controller sent by the user.It seems to me that the error can be corrected by replacing the friendship objects with the corresponding entities lifted from the repositories or better by creating a new instance to ensure that the friendship does not have a preset id.
Finally I get a new instance of the
User
entityowner
from the repository to return the result at the end of the method. This way I make sure that the collection is made up of the persisted entities. (The latter may not be necessary)EDITION I:
I put together a system mimicking the classes you have set up and modified it to make it work. There are probably other decisions I could have made that would make the solution different, i.e. this is one solution but not the only one:
Apart from the change explained in the first answer, I changed the mappings and that change affected other modifications.
User Class
On a personal note, I'd consider removing the collection from
friends
along with the mapping, to deal directly with the entityFriendship
.Friendship class
Controller
In the controller, as Json serialization limited the addition of the friends collection, I added one more endpoint to retrieve a user's friends. The methods are modified to receive form parameters instead of json objects, but this doesn't change the essence.
Services
The same as the first answer plus a method to search for friends.