Hibernate 原生SQL 与 (标量查询、字符串查询、实体查询)

hibernate是支持sql语句查询的,他称之为原生sql,因为他的写法并不是纯sql......

 

 

解决Hibernate原生SQL映射问题
在问答里和论坛中,经常看到有人问,怎样将使用本地SQL查询出来的结果映射为值对象的问题,这里就Hibernate中提供的方法做个结论。前提,
这里没有使用属性的延迟加载技术。

    假设有个值对像,如下:

Java代码

   1. package test;     
   2.     
   3. public class Person {     
   4.     private Long id;     
   5.     private String name;     
   6.     private Long age;     
   7.     private Long phone;     
   8.     private String address;     
   9.     
  10.     public Person(Long id, String name, Long age, Long phone, String address) {     
  11.         this.id = id;     
  12.         this.name = name;     
  13.         this.age = age;     
  14.         this.phone = phone;     
  15.         this.address = address;     
  16.     }     
  17.     
  18.     public Long getId() {     
  19.         return id;     
  20.     }     
  21.     
  22.     public void setId(Long id) {     
  23.         this.id = id;     
  24.     }     
  25.     
  26.     public String getName() {     
  27.         return name;     
  28.     }     
  29.     
  30.     public void setName(String name) {     
  31.         this.name = name;     
  32.     }     
  33.     
  34.     public Long getAge() {     
  35.         return age;     
  36.     }     
  37.     
  38.     public void setAge(Long age) {     
  39.         this.age = age;     
  40.     }     
  41.     
  42.     public Long getPhone() {     
  43.         return phone;     
  44.     }     
  45.     
  46.     public void setPhone(Long phone) {     
  47.         this.phone = phone;     
  48.     }     
  49.     
  50.     public String getAddress() {     
  51.         return address;     
  52.     }     
  53.     
  54.     public void setAddress(String address) {     
  55.         this.address = address;     
  56.     }     
  57. }    
  58.   
  59. package test;  
  60.   
  61. public class Person {  
  62.     private Long id;  
  63.     private String name;  
  64.     private Long age;  
  65.     private Long phone;  
  66.     private String address;  
  67.   
  68.     public Person(Long id, String name, Long age, Long phone, String address) {  
  69.         this.id = id;  
  70.         this.name = name;  
  71.         this.age = age;  
  72.         this.phone = phone;  
  73.         this.address = address;  
  74.     }  
  75.   
  76.     public Long getId() {  
  77.         return id;  
  78.     }  
  79.   
  80.     public void setId(Long id) {  
  81.         this.id = id;  
  82.     }  
  83.   
  84.     public String getName() {  
  85.         return name;  
  86.     }  
  87.   
  88.     public void setName(String name) {  
  89.         this.name = name;  
  90.     }  
  91.   
  92.     public Long getAge() {  
  93.         return age;  
  94.     }  
  95.   
  96.     public void setAge(Long age) {  
  97.         this.age = age;  
  98.     }  
  99.   
 100.     public Long getPhone() {  
 101.         return phone;  
 102.     }  
 103.   
 104.     public void setPhone(Long phone) {  
 105.         this.phone = phone;  
 106.     }  
 107.   
 108.     public String getAddress() {  
 109.         return address;  
 110.     }  
 111.   
 112.     public void setAddress(String address) {  
 113.         this.address = address;  
 114.     }  
 115. }    

package test;   
  
public class Person {   
    private Long id;   
    private String name;   
    private Long age;   
    private Long phone;   
    private String address;   
  
    public Person(Long id, String name, Long age, Long phone, String address) {   
        this.id = id;   
        this.name = name;   
        this.age = age;   
        this.phone = phone;   
        this.address = address;   
    }   
  
    public Long getId() {   
        return id;   
    }   
  
    public void setId(Long id) {   
        this.id = id;   
    }   
  
    public String getName() {   
        return name;   
    }   
  
    public void setName(String name) {   
        this.name = name;   
    }   
  
    public Long getAge() {   
        return age;   
    }   
  
    public void setAge(Long age) {   
        this.age = age;   
    }   
  
    public Long getPhone() {   
        return phone;   
    }   
  
    public void setPhone(Long phone) {   
        this.phone = phone;   
    }   
  
    public String getAddress() {   
        return address;   
    }   
  
    public void setAddress(String address) {   
        this.address = address;   
    }   
}  

package test;

public class Person {
    private Long id;
    private String name;
    private Long age;
    private Long phone;
    private String address;

    public Person(Long id, String name, Long age, Long phone, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.phone = phone;
        this.address = address;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getAge() {
        return age;
    }

    public void setAge(Long age) {
        this.age = age;
    }

    public Long getPhone() {
        return phone;
    }

    public void setPhone(Long phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}  

 

如果查询全部五列记录的话,那么只要

Java代码

   1. List list = getHibernateTemplate().loadAll(Person.class);    
   2.   
   3. List list = getHibernateTemplate().loadAll(Person.class);    

List list = getHibernateTemplate().loadAll(Person.class);  

List list = getHibernateTemplate().loadAll(Person.class);  

 

如果只需要查询id,name,age三列记录呢?那么就要新增构造方法了,

Java代码

   1. public Person(Long id, String name, Long age) {     
   2.     this.id = id;     
   3.     this.name = name;     
   4.     this.age = age;     
   5. }    
   6.   
   7.     public Person(Long id, String name, Long age) {  
   8.         this.id = id;  
   9.         this.name = name;  
  10.         this.age = age;  
  11.     }      

public Person(Long id, String name, Long age) {   
    this.id = id;   
    this.name = name;   
    this.age = age;   
}  

	public Person(Long id, String name, Long age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}    


然后呢,就可以通过HQL来进行查询。

Java代码

   1. List list = getHibernateTemplate().find("select new test.Person(id,name,age) from Person");    
   2.   
   3. List list = getHibernateTemplate().find("select new test.Person(id,name,age) from Person");      

List list = getHibernateTemplate().find("select new test.Person(id,name,age) from Person");  

List list = getHibernateTemplate().find("select new test.Person(id,name,age) from Person");    


这个方法通常可以满足需要了,只是如果,只需要查询id,name,phone三列记录的话,还新增构造方法?不行了,会出现构造方法冲突了。有个办法:

Java代码

   1. List list = getSession().createQuery("select id,name,phone from person").addScalar("id",Hibernate.Long).addScalar("name").
addScalar("phone",Hibernate.Long).addEntity(Person.class);    
   2.   
   3. List list = getSession().createQuery("select id,name,phone from person").addScalar("id",Hibernate.Long).addScalar("name").
addScalar("phone",Hibernate.Long).addEntity(Person.class);    

List list = getSession().createQuery("select id,name,phone from person").addScalar("id",Hibernate.Long).addScalar("name").
addScalar("phone",Hibernate.Long).addEntity(Person.class);  

List list = getSession().createQuery("select id,name,phone from person").addScalar("id",Hibernate.Long).addScalar("name").
addScalar("phone",Hibernate.Long).addEntity(Person.class);  

 
但是,这个只适用于存在Person实体的,如果Hibernate中没有进行Person映射的呢,系统中只存在一个JavaBean。
Java代码

   1. List list = getSession().createSQLQuery("select id /"id/",name /"name/",phone /"phone/" from person")     
   2.                     .addScalar("id",Hibernate.Long).addScalar("name").addScalar("phone",Hibernate.Long)     
   3.                     .setResultTransformer(Transformers.aliasToBean(Person.class)));    
   4.   
   5. List list = getSession().createSQLQuery("select id /"id/",name /"name/",phone /"phone/" from person")  
   6.                     .addScalar("id",Hibernate.Long).addScalar("name").addScalar("phone",Hibernate.Long)  
   7.                     .setResultTransformer(Transformers.aliasToBean(Person.class)));      

List list = getSession().createSQLQuery("select id /"id/",name /"name/",phone /"phone/" from person")   
                    .addScalar("id",Hibernate.Long).addScalar("name").addScalar("phone",Hibernate.Long)   
                    .setResultTransformer(Transformers.aliasToBean(Person.class)));  

List list = getSession().createSQLQuery("select id /"id/",name /"name/",phone /"phone/" from person")
					.addScalar("id",Hibernate.Long).addScalar("name").addScalar("phone",Hibernate.Long)
					.setResultTransformer(Transformers.aliasToBean(Person.class)));    


那么Hibernate就会自动将查出来的三列内容组装到VO对象中去,只是代码量有点大,而且名称都需要重新定义为小写的,在Oracle中查出来的列都默认为大写的
(不知道其它数据库怎么样)

    这个办法就不依赖于构造方法了,只需要定义私有变量,设置getter/setter方法就行了。

    不过如果更猛点的,根本就没有JavaBean对象可以填充怎么办,Hibernate可以将查出来的列组装到集合类中去。如Map。

Java代码

   1.    
   2. List list = getSession().createSQLQuery("select * from person")     
   3.                     .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);    
   4.   
   5. List list = getSession().createSQLQuery("select * from person")  
   6.                     .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);   

 
List list = getSession().createSQLQuery("select * from person")   
                    .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);  

List list = getSession().createSQLQuery("select * from person")
                    .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); 



除了这个Transformers还可以将列转化为List。
Java代码
继承HibernaterDaoSupport
   1. List list = getSession().createSQLQuery("select * from person")     
   2.                     .setResultTransformer(Transformers.T0_LIST);    
   3.   
   4. List list = getSession().createSQLQuery("select * from person")  
   5.                     .setResultTransformer(Transformers.T0_LIST);  

List list = getSession().createSQLQuery("select * from person")   
                    .setResultTransformer(Transformers.T0_LIST);  

List list = getSession().createSQLQuery("select * from person")
                    .setResultTransformer(Transformers.T0_LIST);



到此,还可以通过继承Transformers将结果映射为其它对象,不累述了,基本功能够用了。 

 

 

---------------------出现column not found---------------------

16.1.1. 标量查询(Scalar queries)


最基本的SQL查询就是获得一个标量(数值)的列表。
sess.createSQLQuery("SELECT * FROM CATS").list();sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
它们都将返回一个Object数组(Object[])组成的List,数组每个元素都是CATS表的一个字段值。 Hibernate会使用ResultSetMetadata来判定返回的标量值的
实际顺序和类型。
如果要避免过多的使用ResultSetMetadata,或者只是为了更加明确的指名返回值,可以使用addScalar()。
sess.createSQLQuery("SELECT * FROM CATS") .addScalar("ID", Hibernate.LONG) .addScalar("NAME", Hibernate.STRING) 
.addScalar("BIRTHDATE", Hibernate.DATE)这个查询指定了:

    * SQL查询字符串
    * 要返回的字段和类型


它仍然会返回Object数组,但是此时不再使用ResultSetMetdata,而是明确的将ID,NAME和BIRTHDATE按照 Long,String和Short类型从resultset中取出。
同时,也指明了就算query是使用*来查询的,可能获得超过列出的这三个字段,也 仅仅会返回这三个字段。
对全部或者部分的标量值不设置类型信息也是可以的。
sess.createSQLQuery("SELECT * FROM CATS") .addScalar("ID", Hibernate.LONG) .addScalar("NAME") .addScalar("BIRTHDATE")
基本上这和前面一个查询相同,只是此时使用ResultSetMetaData来决定NAME和 BIRTHDATE的类型,而ID的类型是明确指出的。
关于从ResultSetMetaData返回的java.sql.Types是如何映射到Hibernate类型,是由方言(Dialect)控制的。 假若某个指定的类型没有被映射,
或者不是你所预期的类型,你可以通过Dialet的registerHibernateType调用自行定义。

16.1.2. 实体查询(Entity queries)


上面的查询都是返回标量值的,也就是从resultset中返回的“裸”数据。下面展示如何通过addEntity()让原生查询返回实体对象。
sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").
addEntity(Cat.class);这个查询指定:

    * SQL查询字符串
    * 要返回的实体


假设Cat被映射为拥有ID,NAME和BIRTHDATE三个字段的类,以上的两个查询都返回一个List,每个元素都是一个Cat实体。
假若实体在映射时有一个many-to-one的关联指向另外一个实体,在查询时必须也返回那个实体,否则会导致发生一个"column not found"的数据库错误。
这些附加的字段可以使用*标注来自动返回,但我们希望还是明确指明,看下面这个具有指向Dog的many-to-one的例 子:
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);这样cat.getDog()就能正常运作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值