4

I have a db design that I cannot change. The db has tables and view which have a one to one relationship. The views hold some extra information that is calculated from the table. The relevant information being the status of the row. The permission set up for this relationship is views are read-only where as the tables have all CRUD operations available. JPA was the selected ORM to map to this setup. The app is a basic CRUD app with some validation by checking statuses and other attributes in the view then inserting/updating the corresponding tables. Here is an example of two approaces I have tried to model this case. I was wondering which one is more efficient, easier to work with, and/or the 'correct way' to do this.

Option 1 - This options is nice because I can use all the JPA provided interfaces to interact with the DB. This options is bad because I have to sometimes load a table and a model which seems very redundant and I have 3 files per table.

    Model.java
    package models;
    // relevant imports
    public abstract class Model {
       // columns that are shared with table and view
    }

    Table.java
    package models;
    // relevant imports
    @entity("table")
    public class Table extends Model {
       // Relationships with other tables 
    }

    View.java
    package models;
    // relevant imports
    @entity("view")
    public class View extends Model {
       // View specific columns ...
       // Relationships with other views
    }

Option 2 - This option is nice because I only ever have to load the view and I have one file per table. This option is bad because for the CUD operations I have to write native SQL.

    Model.java
    package models;
    // relevant imports
    @entity("view")
    public class Model {
       // All VIEW + table columns
       // All relationships with other models
       // custom SQL to insert update or delete
    }
jo_wil
  • 369
  • 3
  • 11

1 Answers1

2

I'd specify your view entity as a one to one relationship inside your model object with read only access, if all of your tables all have a corresponding view object. You could do this just by writing getters with no setters, as firing any sort of set then saving will run a failing query. Using inheritance like this would lock you in to having to specify all your columns in one level, and you won't know which columns belong to which tables or views.

    Table.java
    package models;
    // relevant imports
    @entity("table")
    public class Table{
        @OneToOne(mappedBy = "table")
        private View view;
        public string getVariable();
        public string setVaraible();
    }

    View.java
    package models;
    // relevant imports
    @entity("view")
    public class View{
       @OneToOne
       @JoinColumn(name = "table_id")
       private Table table;

       public string getVariable();
       public string getVariable2();
       public string getVariable3();//etc, No setters.

       //alternatively use insertable//updateable=false on all column annotation
       @Column(name="variable_4", insertable =  false, updateable=false)
       public string getVariable4();
    }

Lumping them all together in the model object sort of defeats the object of having the ORM there in the first place, because now you will have to write alot of mysql code to match the ORM's basic CRUD functionality. This would be redundnacy on your end.

Not using inhertiance here leaves inheritance open as an actual option should you choose to use it later down the line. Joining to the view every time may be bad for performance depending on how well your views are written of course, but not having them all in the same object allows for more flexibility in that sense.

Paul Stanley
  • 4,018
  • 6
  • 35
  • 56
  • Thank you this answer is helpful. As a follow up I have some Many to One relationships between tables and I want to update an entire collection of tables would the Join between tables and view be a performance issue. And would EAGER or LAZY fetching be better. My workflow goes 1. get the views to do validation 2. if validation passes update the corresponding table, so this is the step where I need the JOIN to occur – jo_wil Oct 26 '15 at 22:16
  • Hi I have been reading more and more about JPA and stumbled upon the @SecondaryTable annotation that allowed me to map two tables to one class with the view columns added. Is this an equivalent model to yours if I add to the view specific columns the insert=false and update=false? – jo_wil Oct 26 '15 at 22:37
  • @user3211617 you could use that to achieve the secondary scenario you proposed, along with my insert/update=false suggestion, but that also comes with the stipulation of that you will be accessing the view every single time you use the entity. Given on how your application is built, that may be the way to go, but if you are accessing your entity alot for pure crud operations, for example in a REST application, you'd want to keep them seperate. (you dont need to get the view when you POST to, PUT to or DELETE an entity, for example) – Paul Stanley Oct 27 '15 at 09:06
  • thank you so much for your insight and yes my app is accessing the view on every request b/c it needs to check some view specific columns before it can do any of the CRUD operations so I think the overhead of joining every time is a necessary evil. Again thank you. – jo_wil Oct 27 '15 at 16:32