#In UserRoles Bidrectional many to many assoc. Prevent cascade to persist role if that role exist

92 messages · Page 1 of 1 (latest)

marble tusk
#

Problem occures when I try to add new user and set its roles to one that was assigned to previous user.

Error:Detatch entity passed to persist: com.example.UserService.Model.Roles

I want to be able to add user and set roles from user side and on roles table it should add roles if the role doesnt exist..Where am I doing it wrong?

public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;

@Column(unique = true)
private String email;
private String password;

@ManyToMany(cascade = {CascadeType.ALL},fetch = FetchType.LAZY)
@JoinTable(
        name="user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name="role_id")

)
private Set<Roles> UserRoles=new HashSet<>();

}

public class Roles {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String name;

//
@ManyToMany(mappedBy = "UserRoles")

private List<User> users=new ArrayList<>();

}

///////////////// I am setting user as
User ua=new User();

        ua.setEmail("asdasdad");
        ua.setPassword("asdasd");
        ua.setUsername("ua");
        ua.setUserRoles(UserRole);

        User ub=new User();
        ub.setEmail("asdasdada");
        ub.setPassword("asdasda");
        ub.setUsername("ub");
        ub.setUserRoles(MixedRole);

        User uc=new User();
        uc.setEmail("asdasdadaasdas");
        uc.setPassword("asdasda");
        uc.setUsername("uc");
        uc.setUserRoles(UserRole);

userService.save(ua);
userService.save(ub);
userService.save(uc);

karmic brookBOT
#

This post has been reserved for your question.

Hey @marble tusk! Please use /close or the Close Post button above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

burnt junco
marble tusk
# burnt junco Hi <@464818862785953794> not sure what's wrong with your code but I always find ...

think the problem is with trying to cascade existing role again....... At start I create user1...set user1.role to userrole..... user1 is inserted and user role inserts fine also pk link on user_role table is set..... Now if I create user2 ... set user2.role to userrole which exist in the role table which was also set for user 1.....I get error detatched entity passed to persist on model roles....i think it recognizes that userrole was already saved and is currently seperated from session.....

burnt junco
#

Could it be because you are using the same Role object? What if you try to add a "new UserRole" instead?

marble tusk
#

if i create differnet role obj ..its going to create repeatation

burnt junco
#

ok, have you tried the approach from the article? I mean, to have an "add" method instead of only doing a set in user object

marble tusk
#

will check that now

burnt junco
#

Because he is using the same "tag" (roles) for different "post" (users) and it seems to work fine

#
final Long postId = doInJPA(entityManager -> {
    Post post1 = new Post("JPA with Hibernate");
    Post post2 = new Post("Native Hibernate");
 
    Tag tag1 = new Tag("Java");
    Tag tag2 = new Tag("Hibernate");
 
    post1.addTag(tag1);
    post1.addTag(tag2);
 
    post2.addTag(tag1);
 
    entityManager.persist(post1);
    entityManager.persist(post2);
 
    return post1.id;
});
marble tusk
#

yes

marble tusk
#

public void addTag(Tag tag) {
tags.add(tag);
tag.getPosts().add(this);
}

#

.add(this) causes stack overflow error

burnt junco
#

Do you have the code in github? I would like to try to debug it

marble tusk
#

can join vc?

burnt junco
#

no, sorry

marble tusk
#

i do have git hub repo will send it

burnt junco
#

great

marble tusk
#

use user service.... disable @EnableDiscoveryClient ....eureka client from pom......

burnt junco
#

ok

marble tusk
#

or run eureka server and then userservice

burnt junco
#

Having some issues with MySQL server, will ping you later

marble tusk
#

oh

#

i have create-drop enabled.... create database microservice;

burnt junco
#

Not able to fully run it yet but I think It has to do with the lombok hascode and equals

#

Try to choose only the id field for both classes

#

I think that with the lombok annotation it is using all the fields by default

marble tusk
#

i didnt get that

burnt junco
#

So, you added the Data annotation

#

Try to remove that and implement HashCode and Equals

#

But when you do that, don't select all fields, just the ID

#

I was getting the infinite loop but now I don't (getting a different error but it has to do with the DB which is not in my system)

marble tusk
#

still ggetting that error

burnt junco
#

Share the User class please

marble tusk
#

@Getter
@Setter
@peak hedgelArgsConstructor
@NoArgsConstructor
@Entity

public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
private Integer id;
private String username;

@Column(unique = true)
private String email;
private String password;

@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.PERSIST},fetch = FetchType.LAZY)
@JoinTable(
        name="user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name="role_id")

)
private List<Roles> UserRoles=new ArrayList<>();



public void addRoles(Roles roles){
    UserRoles.add(roles);
    roles.getUsers().add(this);
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof User)) return false;
    return id != null && id.equals(((User) o).getId());
}

@Override
public int hashCode() {
    return getClass().hashCode();
}

}

#

can u try h2 database

#

also is there any meaning to this overirde here

burnt junco
#

Yes, it is the way you are going to compare one object against another

#
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
marble tusk
#

oh its from data anot

burnt junco
#

With Data annotation you get it from free BUT it is doing it for all fields

#

And since you have an ID you should only compare objects using that id

marble tusk
#

ok

burnt junco
#

use that hascode for both classes please and try again

marble tusk
#

and what about the ewals method

burnt junco
#
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        return Objects.equals(id, other.id);
    }
marble tusk
#

java: constructor Roles() is already defined in class com.example.UserService.Model.Roles

#

also for user

burnt junco
#

Did you manually add a constructor?

marble tusk
#

using annotation

#

should i remove?

burnt junco
#

No, but you didn't manually add one, right? In addition to the annotation I mean

marble tusk
#

no i didnt add another

burnt junco
#

Error in the IDE, compile error or when you try to run it?

marble tusk
#

build fail

burnt junco
#

oh

#

the equals

#

change the cast

#

is not the same for both clases

#

You would need to adapt the line before the last one

marble tusk
#

on this User other = (User) obj;?

burnt junco
#

yes, that is fine for User

#

but need to change for Roles

marble tusk
#

to

burnt junco
#

Roles other = (Roles) obj;

marble tusk
burnt junco
#

Do you have compile errors? Before trying to run the build I mean, do you see any red alert?

marble tusk
#

fails at build

#

let me try to use all args constructor for user and roles instanse

burnt junco
#

In order to try to solve the first issue, just remove the 2 constructor annotation from lombok and manually add the one that you need

marble tusk
#

back to detached entity

burnt junco
#

damn

#

Just for the sake of trying, could you remove the "trasactional" annotation from both?

marble tusk
#

it is without that

burnt junco
#

will try to test it with an H2 database, will ping you later

marble tusk
#

ok

#

u try your way to insert user and roles ...cascading parent to child

burnt junco
#

Looks like since the session is being closed by the "save" the object needs to be retrieved from DB before assigning it to the second User

#

The only thing to have in mind is to also fetch the Users in the same call to get the Role because if not it is going to throw a LazyInitialization Exception

marble tusk
#

lets go finally its working

#

removed allargsconstructor.....add cascade all and fetch to eager on both user and roles

burnt junco
#

Happy to hear that!

marble tusk
#

ok the problem was with my insertion....we dont need @data as well

burnt junco
#

You can use Data if you want, it is going to save you from a lot of boilerplate but you have to be careful because the default configuration could not be ideal

karmic brookBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.

marble tusk