postgresqljdbcmicronautmicronaut-data

Micronaut JDBC Many to Many relationship


I'm trying to create a Many to Many relationship in Micronaut, but it doesn't seem to work. Using postgreSQL and micronaut-data-jdbc 3.9.3

SQL:

CREATE TABLE project
(
    id          SERIAL PRIMARY KEY,
    ...
);

CREATE TABLE user
(
    id    SERIAL PRIMARY KEY,
    ....
);

CREATE TABLE project_user
(
    user_id    INTEGER REFERENCES user (id),

    project_id INTEGER REFERENCES project (id),

    CONSTRAINT users_projects_pk PRIMARY KEY (user_id, project_id)
);

Java code:

public class User {
    @Id
    @GeneratedValue
    private Integer id;
    ....

    @Relation(value = Relation.Kind.MANY_TO_MANY, mappedBy = "users")
    private Set<Project> projects = Collections.emptySet();
}
public class Project {
    @Id
    @GeneratedValue
    private Integer id;
    ...
    @Relation(value = Relation.Kind.MANY_TO_MANY)
    @JoinTable(
        name = "project_user",
        joinColumns = @JoinColumn(name = "project_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id"))
    @JsonIgnore
    private Set<User> users;
}

Example useage:

        var users = userRepository.findByIdInList(userIdList);

        Project project = Project.builder()
            .users(users)
            .build();
        project = projectRepository.save(project);

The project is generated with all of it's properties and saved in the database. However there is no record in the project_user table.

Am I missing something?


Solution

  • You aren't telling Micronaut to cascade the changes to Project.

        //@Relation(value = Relation.Kind.MANY_TO_MANY)
        @Relation(value = Relation.Kind.MANY_TO_MANY, cascade = Relation.Cascade.ALL)
        @JoinTable(
                name = "project_user",
                joinColumns = @JoinColumn(name = "project_id"),
                inverseJoinColumns = @JoinColumn(name = "user_id"))
        private Set<User> users;
    

    The default for cascade is NONE, do nothing.

    public @interface Relation {
        /**
         * @return The relation kind.
         */
        Kind value();
    
        /**
         * @return The inverse property that this relation is mapped by
         */
        String mappedBy() default "";
    
        /**
         * How to cascade insert/delete operations to the associated entity. Default is none.
         * @return The cascade handling
         */
        Cascade[] cascade() default Cascade.NONE;
    
        /**
         * Cascade type handling for different associations. Cascading delete is not yet supported.
         */
        enum Cascade {
            /**
             * Cascade all operations.
             */
            ALL,
            /**
             * Cascade insert operations.
             */
            PERSIST,
            /**
             * Cascade update operations.
             */
            UPDATE,
             /**
             * Don't cascade.
             */
            NONE
        }