java - Map some boolean properties as enum Set in Hibernate -


i have entity has bit fields database:

  • editable
  • needs_review
  • active

these fields mapped against boolean fields in java class using hibernate 3.6.9 version. forces me write interface method each list of entities want get:

list<entity> listeditables(); list<entity> listreviewneeded(); list<entity> listactives(); 

or write general interface method achieve combination of them:

list<entity> listentities(boolean editables, boolean reviewneeded, boolean actives); 

that second choice looks greater, if add field in future there need modify interface (and every line of code coupled it).

so decided can express enumeration set:

public enum entitytype{     editable, review_needed, active }  //that way there's no need change interface method's signature list<entity> listentities(set<entitytype> requiredtypes); 

it makes sense being enumeration match want achieve, entity type should have own set<entitytype>:

public class entity{     set<entitytype> entitytypes; } 

however instead of have mapped booleans logically match set. question, there way map set<entitytype> entitytypes in hibernate based in bit fields or have manage logic myself having them boolean?

update

having them mapped set implies possibility of querying list using in clause, if not imply step conversion between controller , model codes.

set<entitytype> typesset = sets.newhashset(entitytype.editable, entitytype.review_needed); //obtains list of every single entity editable or review_needed session.createcriteria(entity.class).addrestriction(restrictions.in("entitytypes",typeset)).list(); 

i think have solution you. interested in compositeusertype.

as example lets use inetaddress composite user type wrote lately map 128bit ipv6 address / ipv4address object 2 64bit long properties inside user account entity.

the signupip:inetaddress mapped towards 2 columns (there no column count limit or alike) using:

    @columns(columns = {@column(name = "ip_low", nullable = true), @column(name = "ip_high", nullable = true)})     private inetaddress signupip; 

and interesting part of implementation looks this:

public class inetaddressusertype implements compositeusertype { @override public string[] getpropertynames() {     return new string [] {"iplow", "iphigh"}; }  @override public type[] getpropertytypes() {     return new type [] { longtype.instance, longtype.instance}; }  @override public object getpropertyvalue(object component, int property) throws hibernateexception {     if(component != null)         return tolong((inetaddress)component)[property];     else         return null; }  @override public void nullsafeset(preparedstatement st, object value, int index,         sessionimplementor session) throws hibernateexception, sqlexception {      if(value != null) {         long [] longs = tolong((inetaddress)value);         st.setlong(index, longs[0]);         st.setlong(index + 1, longs[1]);     }     else {         st.setnull(index, longtype.instance.sqltype());         st.setnull(index + 1, longtype.instance.sqltype());     } }  @override public void setpropertyvalue(object component, int property, object value)         throws hibernateexception {     throw new runtimeexception("this object immutable"); }  @override public class<?> returnedclass() {     return inetaddress.class; }  @override public boolean equals(object x, object y) throws hibernateexception {     return x != null ? x.equals(y) : null == y; }  @override public int hashcode(object x) throws hibernateexception {     return x.hashcode(); }  @override public object nullsafeget(resultset rs, string[] names,         sessionimplementor session, object owner)         throws hibernateexception, sqlexception {     long iplow = rs.getlong(names[0]);     if(!rs.wasnull()) {         long iphigh = rs.getlong(names[1]);          try {             return fromlong(new long [] {iplow, iphigh});         } catch (unknownhostexception e) {             throw new hibernateexception("failed inetaddress: ip = " + iphigh + " + " + iplow, e);         }     }     else         return null; }  @override public object deepcopy(object value) throws hibernateexception {     if(value != null)         try {             return inetaddress.getbyaddress(((inetaddress)value).getaddress());         } catch (unknownhostexception e) {             throw new runtimeexception("impossible exception: " + e.getmessage(), e);         }     else         return null; }  @override public boolean ismutable() {     return false; }     ...  } 

note flexibly switch between inet4address , inet6address instances depending on values of iplow , iphigh. composite marked immutable , need check documentation , examples in hibernate source code (build in composite user types).

in similar way can map meaningful bit properties. can query bits using single restriction.eq refering enumtype. can use equals method check properties object. , if need refer special mapped bit can use dot notation in signupip.iplow refer iplow property/column.

i guess looking for.

update:

in end boils down define right order of properties. hibernate use integer index values access each property:

//immutable simplicity class status {      private final boolean editable;      private final boolean needsreview;      private final boolean active;      //... constructor + iseditable etc.. } 

in statuscompositetype class:

public string[] getpropertynames() {   return new string [] {"editable", "needsreview", "active"}; }  public type[] getpropertytypes() {   return new type [] { booleantype.instance, longtype.instance}; }  public object getpropertyvalue(object component, int property) throws hibernateexception { if(component != null) {    status status = (status)component;    switch(property) {    case 1: return status.iseditable();    case 2: return status.isreviewneeded();    case 3: return status.isactive();    default: throw new illegalargumentexception();    } } else     return null; //all columns can set null if allow entity have null status. }   public void nullsafeset(preparedstatement st, object value, int index,     sessionimplementor session) throws hibernateexception, sqlexception {    if(value != null) {     status status = (status)value;     st.setboolean(index, status.iseditable());     st.setboolean(index + 1, status.isreviewneeded());     st.setboolean(index + 2, status.isactive());   }   else {     st.setnull(index, booleantype.instance.sqltype());     st.setnull(index + 1, booleantype.instance.sqltype());     st.setnull(index + 2, booleantype.instance.sqltype());   } }  public object nullsafeget(resultset rs, string[] names,     sessionimplementor session, object owner)     throws hibernateexception, sqlexception {   boolean iseditable = rs.getboolean(names[0]);   if(!rs.wasnull()) {     boolean isreviewneeded = rs.getboolean(names[1]);     boolean isactive = rs.getboolean(names[2]);      return new status(iseditable, isreviewneeded, isactive);   }   else     return null; } 

the rest straight forward. remember implement equals , hashcode user type , add type configuration before create sessionfactory.

once have in place can create criteria search , use:

//search elements have status of editable, no reviewneeded , not active (true false false). criteria.add(restrictions.eq("status", new status(true, false, false)); 

now listentities method may become either: listentities(status status) or listentities(boolean editable, boolean reviewneeded, boolean isactive).

if need additional information check compositetype , basictype implementations hibernate provides within own sourcecode (look implementors of compositetype , basictype). understanding helps alot use , learn intermediate level knowledge of hibernate.


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -