简体   繁体   中英

JPA POJO of joined table in Java

What I would like to realize is the following:

I have a dashboard class and a user class. In my (Java EE project) Java code I would like to get all dashboards, to which the user has been subscribed.

The database contains a table (dashboard_users), with the following fields: idUser, idDashboard, isDefault en ID. There should also be a Java POJO of the joined tabled.

My question:

  • How should the JPA MM connection between these three classes look like (Dashboard.java/User.java/UserDashboard.java)?

I followed a lot of tutorials and examples, but for some reason there are always errors or other problems. It would be very welcome if someone could give an example, so I can see what I am doing wrong.

Thank you

Given the extra attribute on the association table you are going to need to model it (via a UserDashboard.java class as you asked). Quite unfortunate, as it adds a significant amount of work to your model layer.

If you find you do not need the extra attribute after all then I would model User with a set of Dashboards, linked directly via a @JoinTable .

One way you could do this would be to see the relationship between User and Dashboard as a map in which the Dashboard is a key, there being an entry for every Dashboard associated with the User , and the value is a flag indicating whether that Dashboard is the default for that User . I admit this is a bit forced; it's an odd way to look at the relationship, perhaps even suspect as has been charged.

But the advantage of this view is that it lets you map the living daylights out of everything like this:

@Entity
public class Dashboard {

    @Id
    private int id;
    private String name;

    public Dashboard(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected Dashboard() {}

}

@Entity
public class User {

    @Id
    private int id;
    private String name;
    @ElementCollection
    private Map<Dashboard, Boolean> dashboards;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
        this.dashboards = new HashMap<Dashboard, Boolean>();
    }

    protected User() {}

    // disclaimer: the following 'business logic' is not necessarily of the finest quality

    public Set<Dashboard> getDashboards() {
        return dashboards.keySet();
    }

    public Dashboard getDefaultDashboard() {
        for (Entry<Dashboard, Boolean> dashboard : dashboards.entrySet()) {
            if (dashboard.getValue()) {
                return dashboard.getKey();
            }
        }
        return null;
    }

    public void addDashboard(Dashboard dashboard) {
        dashboards.put(dashboard, false);
    }

    public void setDefaultDashboard(Dashboard newDefaultDashboard) {
        Dashboard oldDefaultDashboard = getDefaultDashboard();
        if (oldDefaultDashboard != null) {
            dashboards.put(oldDefaultDashboard, false);
        }
        dashboards.put(newDefaultDashboard, true);
    }

}

This maps a table structure which looks like this Hibernate-generated SQL , which i think is roughly what you want. The generated names on the User_dashboards table are pretty shoddy; you could customise them quite easily with some annotations or some XML. Personally, i like to keep all the filthy details of the actual mapping between the objects and the database in an orm.xml ; here's what you'd need to add to use more sensible names:

<entity class="User">
    <attributes>
        <element-collection name="dashboards">
            <map-key-join-column name="Dashboard_id" />
            <column name="is_default" />
        </element-collection>
    </attributes>
</entity>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM