java - JPA: left join without @OneToMany annotations -


i have onetomany relationship in db don't want hibernate manages directly.

this relationships translations, dto represents translated registry:

@entity @table(name = "my_table") public class mytable {      @id     @column(name = "id", nullable = false, unique = true)     private integer id;      @transient     private string lang;      @transient     private string text;      // getters , setters     ... }  @entity @table(name = "my_table_translation") public class mytabletranslation {      @id     @column(name = "id", nullable = false, unique = false)     private integer id;      @id     @column(name = "lang", nullable = false, unique = false, length = 2)     private string lang;      @column(name = "text", nullable = false, unique = false, length = 200)     private string text;      // getters , setters     ... } 

i want have specific findall(string lang) method lang parameter, , use specification criteria build query. that:

public void findall(string language) {     list<mytable> list = repository.findall(new specification<mytable>() {         @override         public predicate topredicate(root<mytable> root, criteriaquery<?> query, criteriabuilder cb) {             // there             return ...;         }     }); } 

the fact don't know how that, because can't use join clause, have not attribute in model represents relationship.

i tried use select...from...left join query sql notation,

select t1, t2 mytable t1 left join mytabletranslation t2 on t1.id = t2.id 

and works, not desired. resulting list of objects, list of 2 object per item: 1 mytable object, , other mytabletranslation related object. need parse list , programatically build objects using propertyutils class apache commons library.

it not clean think... know how make easy, without using sql notation?

marc, can following make work , not need complicated join clauses or predicate right now. simple implementation in embedded h2 database , junit testing sufficient proof of concept (poc) below

note:

  1. i using spring + plain jpa hibernate implementation poc.
  2. i using spring recommended way of managing transaction.
  3. com.mycompany.h2.jpa package contains entity classes.
  4. take @ mytable.sql has similar structure needs.

mytable.java

@entity @table(name = "my_table") public class mytable implements serializable {      private static final long serialversionuid = 1l;      @id     @generatedvalue(strategy=generationtype.identity)     @column(name = "id", nullable = false, unique = true)     @joincolumn(referencedcolumnname="id", insertable=true, updatable=false)     private long id;      @column(name = "lang", unique=true)     private string lang;      @column(name = "text")     private string text;          @onetomany(fetch = fetchtype.lazy)     @joincolumn(name="id", insertable=true, updatable=true, referencedcolumnname="id")     private list<mytabletranslation> translations = new arraylist<mytabletranslation>();     ...     // getters , setters, tostring() }    

mytabletranslation.java

@entity @table(name = "my_table_translation") public class mytabletranslation implements serializable {      private static final long serialversionuid = 11l;      @id     @column(name = "id")     private long id;      @id     @column(name = "speaker")     string speaker;     ...     // getters , setters, tostring() } 

testh2databaseconfiguration.java

@configuration @enabletransactionmanagement public class testh2databaseconfiguration {      final static logger log = loggerfactory.getlogger(testh2databaseconfiguration.class);      @bean     @qualifier("datasource")     public datasource h2datasource() {         return new embeddeddatabasebuilder().settype(embeddeddatabasetype.h2).addscript("classpath:mytable.sql").build();     }      @bean     public entitymanagerfactory entitymanagerfactory() {          hibernatejpavendoradapter jpavendoradapter = new hibernatejpavendoradapter();         jpavendoradapter.setgenerateddl(true);          localcontainerentitymanagerfactorybean factorybean = new localcontainerentitymanagerfactorybean();          factorybean.setdatasource(h2datasource());         factorybean.setjpavendoradapter(jpavendoradapter);         factorybean.setpackagestoscan("com.mycompany.h2.jpa");         factorybean.setpersistenceunitname("my_table");          properties prop = new properties();         prop.put("hibernate.dialect", "org.hibernate.dialect.h2dialect");         prop.put("hibernate.show_sql", "true");         prop.put("hibernate.hbm2ddl.auto", "none");         factorybean.setjpaproperties(prop);          factorybean.afterpropertiesset();          return factorybean.getobject();     }      @bean     public platformtransactionmanager transactionmanager() {         jpatransactionmanager txmanager = new jpatransactionmanager();         txmanager.setentitymanagerfactory(entitymanagerfactory());         return txmanager;     }      @bean     public mytabledao mytabledao() {         return new mytabledaojpaimpl();     }      @bean     public mytableserviceimpl mytableservice() {         mytableserviceimpl mytableservice = new mytableserviceimpl();         mytableservice.setmytabledao(mytabledao());         return mytableservice;     } } 

mytableservice.java

public interface mytableservice {        public mytable savemytabletranslation(mytable mytable);     public list<mytable> getallmytables();     public mytable getmytable(long entityid);     public mytable getmytable(string lang); } 

mytableserviceimpl.java

@transactional public class mytableserviceimpl implements mytableservice {      final static logger log = loggerfactory.getlogger(mytableserviceimpl.class);      private mytabledao mytabledao;      public void setmytabledao(mytabledao mytabledao) {         this.mytabledao = mytabledao;     }         public mytable savemytabletranslation(mytable mytable) {         return mytabledao.savemytabletranslation(mytable);     }      public list<mytable> getallmytables() {         return mytabledao.getallmytables();     }      public mytable getmytable(long entityid) {         return mytabledao.getmytable(entityid);     }      public mytable getmytable(string lang) {         return mytabledao.getmytable(lang);     } } 

mytabledao.java

public interface mytabledao {     public mytable savemytabletranslation(mytable mytable);     public list<mytable> getallmytables();     public mytable getmytable(long entityid);     public mytable getmytable(string lang); } 

mytabledaojpaimpl.java

public class mytabledaojpaimpl implements mytabledao {      final static logger log = loggerfactory.getlogger(mytabledaojpaimpl.class);      @persistencecontext     private entitymanager entitymanager;      public mytable savemytabletranslation(mytable mytable) {         entitymanager.persist(mytable);         return mytable;     }      @suppresswarnings("unchecked")     public list<mytable> getallmytables() {         return (list<mytable>) entitymanager.createquery("from mytable").getresultlist();            }      public mytable getmytable(long entityid) {         return (mytable) entitymanager.createquery("from mytable m m.id = :id ").setparameter("id", entityid).getsingleresult();     }      public mytable getmytable(string lang) {         return (mytable) entitymanager.createquery("from mytable m m.lang = :lang ").setparameter("lang", lang).getsingleresult();     } } 

mytabletest.java (a junit test class)

@runwith(springjunit4classrunner.class) @contextconfiguration(classes = { testh2databaseconfiguration.class }, loader = annotationconfigcontextloader.class) public class mytabletest extends abstracttransactionaljunit4springcontexttests {      final static logger log = loggerfactory.getlogger(mytabletest.class);      @autowired     @qualifier("mytableservice")     mytableservice mytableservice;         @test     public void test() throws parseexception {          mytable parent = new mytable();         parent.setlang("italian");         parent.settext("fast...");          mytabletranslation child = new mytabletranslation();         child.setspeaker("liotta");          parent = mytableservice.savemytabletranslation(parent);          log.debug("parent id : " + parent.getid());          mytable spanishtables= mytableservice.getmytable("spanish");         list<mytabletranslation> spanishtranslations = spanishtables.gettranslations();         log.debug("spanishtranslations size : " + spanishtranslations.size());          (mytabletranslation mytabletranslation : spanishtranslations) {             log.debug("mytabletranslation -> : " + mytabletranslation);         }            } } 

mytable.sql

create table if not exists my_table (   id      identity primary key,   lang    varchar unique,   text    varchar );  delete my_table; insert my_table values (1, 'spanish', 'beautiful...'); insert my_table values (2, 'english', 'great...'); insert my_table values (3, 'french', 'romantic...');   create table if not exists my_table_translation (   id      integer,   speaker varchar );  delete my_table_translation; insert my_table_translation values (1, 'eduardo'); insert my_table_translation values (1, 'diego'); insert my_table_translation values (2, 'george'); insert my_table_translation values (3, 'pierre'); 

Comments

Popular posts from this blog

sql - invalid in the select list because it is not contained in either an aggregate function -

Angularjs unit testing - ng-disabled not working when adding text to textarea -

How to start daemon on android by adb -