• java之Hibeante中SQL语句的使用


    批量更新

    //查询User表中的所有记录

         ScrollableResults uScrollableResults = session.createQuery("from User")

                                       .setCacheMode(CacheMode.IGNORE)

                                       .scroll(ScrollMode.FORWARD_ONLY);

         int count = 0;

         //遍历User表中的全部记录

         while(uScrollableResults.next()) {

            User user = uScrollableResults.get(0);

    //      user.setFullName(fullName);

            user.setName("newName");

            if(++count % 20) {

               session.flush();

               session.clear();

            }

         }

    DML风格的批量更新

    String hqlUpdate = "update User u set name= :newName";

         //执行更新

         int updateEntities = session.createQuery(hqlUpdate)

               .setString("newName", "新名字")

               .executeUpdate();

    String halDelete = "delete User";

         //执行删除

         int deleteEntities = session.createQuery(halDelete)

               .executeUpdate();

    1HQL查询

    HQL是 Hibernate Query Language的缩写,HQL的语法很像SQL的语法,但HQL是一种面向

    的查询语言。SQL的操作对象是数据表、列等数据库对象,而HQL的操作对象是类、实例、属性等。

    HQL是完全面向对象的查询语言,因此可以支持继承、多态等特性。

    HQL查询依赖于 Query类,每个Quey实例对应一个查询对象。使用HL查询按如下步骤进

    获取 Hibernate Session对象。

    ②编写HQL语句。

    ③3)以HQL语句作为参数,调用 Session的 createQuery方法创建查询对象

    ④如果HQL语句包含参数,则调用Query的 setXxx()方法为参数赋值。

    ⑤5调用 Query对象的list()或 uniqueResult()方法返回查询结果列表(持久化实体集)

    下面的查询示例示范了HQL查询的基本用法。

         //以HQL语句创建Query对象

         List pl =session.createQuery("select distinct p from Person p" + "join p.myEvents where title= :eventTitle")

               //执行setString()方法为HQL语句的参数赋值

               .setString("eventTitle", "表态")

               //Query()调用list()方法获取查询的全部实例

               .list();

    List pl1 = session.createQuery("select distinct p from Person p"

               + "inner join p.myEvents event where event.happenDate"

               + "between :firstDate and : endDate")

               //设置参数

               .setDate("firstDate", start)

               .setDate("endDate", new Date())

               //返回结果

               .list();

        

         List pl2 = session.createQuery("select distinct p.id, p.name, p.age"

                    + "from Person p join p.myEvents")

               //Query调用list()方法访问查询得到的全部属性

               .list();

    Query还包含如下两个方法

    setFistResult(int firstResult):设置返回的结果集从第几条记录开始

    setMaxResult(int maxResult):设置本次查询返回的结果数目

    这两个方法用于对HQL查询实现分页查询

    关联和连接:

    HQL支持两种关联连接形式:隐式与显式

    HQL查询到的from字句

           隐式连接形式不使用join关键字,使用英文点号来隐式连接关联实体,而Hibernate底层将自动进行关联查询。

           //使用Implict查询Person持久化实体 p.myEvent属性是一个持久化实体

    From Person p where p.myEvent.title > :title

           //使用显式连接

    From Person p inner join p.myEvent event where event.happenDate < :endDate

    使用显式连接时可以为相关联的实体,及关联集合中的全部元素指定一个别名

    连接的集中方式

    1>inner join(内连接),可简写成join

    2>left outer join(左外连接),可简写成left join

    3>right outer join (右外连接),可简写成right join

    4> full join(全连接)

    使用with 提供额外的连接

    //使用显式连接

    from Person p

    inner join p.myEvent event wiih p.id > event.id where event.happenDate < :endDate

    如果myEvents是个集合

    返回一个集合[集合元素是Person实体和MyEvent实体组成的数组]

    Select p from Person p inner join p.myEvents e where e.title = :eventTitle

    返回Person实体组成的集合,且元素不重复

    Select distinct p from Person p inner join p.myEvents e where e.title = :eventTitle

    如果Person对象中的属性是集合属性,则加载实体时,系统采用默认懒加载方法

    避免懒加载的方法如下:

    1. 在Hibernate持久化注解中指定fetch=FetchType.EAGER来关闭延迟加载
    2. 使用join fetch   例如:from Person as p join fetch p.scores

    使用fetch关键字应注意以下几点

    1> fetch不应该与 setMaxResults()或 setFirstResult()共用。因为这些操作是基于结果集的,而在预先抓取集合类时可能包含重复的数据,即无法预先知道精确的行数

    2> fetch不能与独立的with条件一起使用。

    3>如果在一次查询中 fetch多个集合,可以查询返回笛卡儿积,因此请多加注意

    4> full join fetch与 right join fetch是没有任何意义的

    如果在持久化注解中映射属性时通过指定 fetch= FetchType.LAZY启用了延迟加载(这种延迟加载是通过字节码增强来实现的),然后程序里又希望预加载那些原本应延迟加载的属性,则可以通过fetch all properties来强制 Hibernate立即抓取这些属性。

    from Document fetch all properties order by name

    from Document doc fetch all properties where lower(doc.name) like ‘%cats%’

    HQL查询的select字句

    Select p.name from Person as p

    //还可以选择组件属性包含的属性

    select p.name.firstName from Person as p

    //select选出的多项存入List对象中

    select new list(p.name,p.address) from Person as p

    //将选择出的对象封装成对象[前提是ClassTest支持这些属性的构造器]

    select new ClassTest(p.name, p.address) from Person as p

    //给选中的表达式命名别名

    select p.name as personName from Person as p

    select new map(p.name, as personName) from Person as p   //返回一个集合

    HQL查询的聚集函数

    1>avg

    2>count:

    3>max

    4>min

    5>sum:

    select count(*) from Person

    select max(p.age) from Person as p

    selct支持字符串连接符、算数运算符,以及SQL函数

    select p.name || “” || p.address from Person as p

    多态查询

    From后跟类名、或接口,则查询该持久化类,及子类或则实现该接口的所有实例

    Where查询

    只要不出现集合HQL语句可使用点号来隐式连接多个数据表

    from Foo foo where foo.bar.customer.address.city like “Guangzhou%”

    生成一个四表连接的查询语句【=运算符既可以比较属性,又可以比较实例】

    From Cat cat, Cat rival where cat.mate = rival.mate select cat, mate from Cat cat, Cat mate where cat.mate = mate

    Id作为组件类型的标识符使用

    from Person as person where person.id.country = ‘au’

    and person.id.medicareNumber = 1234

    from Account as account where account.owner.id.country = ‘AU’

    and account.owner.id.medicareNumbber = 123456

    嵌入where字句的java类名,将作为辨别者值

    //执行多台查询时,默认会选出Cat及其所有子类的实例

    From Cat cat where cat.class = DomesticCat

    另外当where子句中的运算符只支持基本类型或字符串时,where子句中的属性表达式必须以基本类型或字符串结尾

    //例如 Account.Person,而person.Name组件 时where子句示例

    from Account as a where a.person.name.firstName like “dd%”

    Where子句支持的表达式表达式

    1. 数学运算符:+ - * /
    2. 二进制比较运算符: = >= <= <> != like
    3. 逻辑运算符:and、or、not
    4. in, not in, between, is null, is not null, is empty, is not empty、 membet of and not member of
    5. 简单的case,case…when,..then..else....end和case、 case when…then,..then..end等
    6. 字符串连接符:如 value1  || value2,或使用字符串连接函数concat(value1,value2)
    7. 时间操作函数: current_date()、 current_time(), current_timestamp()、second()、minute()、hour()、day()、month()、year()等
    8. 还支持EJB-QL3.0所支持的函数或操作: substring().trim(). lower(),upper()、length()、locate()、abs()、sqrt()、bit_length()、coalesce()和nullif()
    9. 支持数据库的类型转换函数,如cast(…as…),第二个参数是 Hibemate的类数名,或者extract(…from…),前提是底层数据库支持 ANSI cast()和extract().
    10. 如果底层数据库支持单行函数:sign(), trunc()、 rtrim(), sin().则HOL通句也完全复持,
    11. HQL语句支持使用命名参数作为占位符,方法是在参数名前英交加冒号(:)等:也支持使用英文问号+数字的形式(?N)的参数作为占位,
    12. 当然,也可以在 where子句中使用SQL常量, ,还可以在HQL语句中使用Java中的 public static final类型的常量,例如 Color.RED
    13. 除此之外, where子句还支持如下的特殊关键字用法
    14. HOL index()函数,作用于join的有序集合的别名
    15. HQL函最,把集合作为参数:size()、 minelement(),maxelement(), minindex(). maxindex()

    有特别的 elements()和 indices()函数,可以用数量词加以限定,如same、all、exists、any、in

    16.in与 between…..and

    from DomesticCat cat where cat.name between ' A and'B'

    from DomesticCat cat where cat. name in (‘Foo,'Bar,'Bar')

    from DomesticCat cat where cat,name not between ‘A’ and'B’

    from DomesticCat cat where cat. name not in ('Foo','Bar’,’Baz’)

    17.子句 is null与 is not nul可以被用来测试空值。

    from DomesticCat cat where ca.name is null

    from person as p where p.address is not null

    18.如果在 Hibernate配置文件中进行如下声明

    <property name="hibernate.query,.substitutions">true I, false 0</property>

    上面的声明表明:HQL转换SOL语句时,将使用字符1和0来代替关键字true和false,然后就可以在表达式中使用1和0来构建布尔表达式了。

    from Cat cat where cat,.alive= 0

    19.size关键字用于返回一个集合的大小,例如:

    from Cat cat where cat.kittens.size >0; from Cat cat where size(cat..kittens) > 0

    20.对于有序集合,还可使用 minindex()与 maxindex()函数代表最小与最大的索引序数。

    可以使用 minelement()与 maxelemet()函数代表集合中最小与最大的元素,例如

    from Calendar cal where maxelement(cal.holidays) > current_date;

    from Order where maxindex(order.items) > 100;

    from Order where where minelement(order.items)> 100;

    21.还有特别有用的 elements()和 indices()函数,用于返回指定集合的所有元素和所有索引值。还可以any、some、all、exists、in等SQL函数操作集合里的元素,例如

    //操作能合元素

    Select mother from Cat an mother, Cat as kit where kit in elements(foo.kittens)

    //p的name属性等于集合中某个元素的name属性

    Select p from NameList list, Person p where p.name = some elements(list.names)

    //操作集合元素

    from Cat cat where exists elements(cat.kittens)

    from Player p where 3 > all elements(p.scores)

    from Show show where ‘fizard’ in indices(show.acts)

    22.值得指出的是,这些结构变量: size elements, indices. minindex; maxindex, inclement.,max

    在where子句中,有序集合(数组、List集合、Map对象)的元素可以通过们运算符访问,例

    等,只能在 where子句中使用

    //item是有序集合性

    from Order order where order items [0].id-12347

    //holidays是Map集合属性, holidays[‘national’]代表key为 nationa1的元素

    Select person from Person person, Caledar calendar where calendar.holidays[‘national day’] = person.birthDay and person.nationlity.calendar = calendar;

    //下同时使用List集合和Map集合属性

    select item from Item item, order order where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11;

    select item from Item item, Order order where order items[ maxindex(order.items) ] = item and order.id = 11;

    23.在[]中的表达式甚至可以是一个算术表达式。例如

    Select item form Item item, Order order where order.items[size(order.items) - 1] = item;

    order by子句

    查询返回的集合可以根据类或组件属性的任何属性进行排序。例如:

    from Person as p order by p.name, p.age

    还可使用asc或desc关键字指定升序或降序的排序规则。例如:

    from Person as p order by p.name asc, p.age desc

    如果没有指定排序规则,则默认采用升序规则。

    group by子句

    //返回聚集值的查询可以对持久化类或组件属性的属性进行分组,分组使用 group by子句,

    select cat.color, sum(cat.weight), count(cat) from Cat cat group by cat.color

    类似于SQL的规则,出现在select后的属性,要么出现在聚集函数中,要么出现在 group by的属性列表中,看下面的示例:

    //select后出现的id处于group by 之后,而name属性则出现在聚集函数中

    select foo.id, avg(name), max(name) from Foo foo join foo.names name group by foo.id

    //having子句用于对分组进行过滤,[having字句只能在group by字句时才可以使用]

    select cut.color, sum(cat.weight), count (cat) from Cat cat group by cat. color having cat.color in (eg.Color.TABBY,eg.Color.BLACK)

    /****如果底层数据库支持having字句和group子句中使用普通函数或聚集函数,则HQL的having与order by字句也可以使用普通函数和聚集函数

    order by 和 group by子句不能包含算术表达式

    *********/

    select cat from Cat cat join cat.kittens kitten group by cat having avg(ktten.weight) > 100

    order by count (kitten) asc,sum(kitten.weight) desc

    子查询

    在HQL中,子查询要用英文括号()括起来,HQL子查询值可以在select子句或者where子句中出现

    from Cat as fatcat where fatcat.weight > (select avg(cat.wegiht) from DomesticCat cat);

    from Cat as cat where not( cat.name, cat.color) in (select cat.name, cat.color from DomesticCat cat);

    //子查询在select之后

    from DomesticCat as cat where cat.name not in (select name.nickName from Name as name)

    select cat.id, (select max(kit.weight) from cat.kitten kit) from Cat as cat

    命名查询

    HQL支持吧查询的HQL语句放入注解注解中,且使用@NameQuery注解来配置命名查询,可以使用@NameQueries来组合多个@NameQuery

    支持的属性如表

    属性

    是否必须

    说明

    name

    指定命名的名称

    query

    指定命名查询所使用的HQL查询语句

    使用示例

    @Entity

    @Table(name="person_inf")

    //定义命名查询

    @NamedQuery(name="myNameQuery", query = "from Person as p where p.age > ?")

    public class Person{}

    //在Session中使用getNameQuery(String name)方法,创建一个Query对象

    void findByNamedQuery() throws Exception{

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction session.beginTransaction();

                  List pL= session.getNamedQuery("myNamedQuery")

                                //根据HQL语句里的参数索引为参数赋值

                                .setInteger(0, 20)

                                .list();

                  //....

                 

                  txTransaction.commit();

                  HibernateUtil.coloseSession();

                 

           }

    条件查询

    条件查询是更具面向对象特色的数据查询方式。条件查询通过如下三个类完成。

    Criteria:代表一次查询。

    Criterion:代表一个查询条件。

    Restrictions生查询条件的工具类。

    执行条件查询的步骤如下。

    ①获得 Hibernate的 Session对象。

    2以 Session对象创建 Criteria对象。

    3使用 Restrictions的静态方法创建 Criterion查询条件。

    向 Criteria查询中添加 Criterion查询条件。

    5执行 Criteria的lsO或 uniqueResul0方法返回结果集

    看下面的条件查询的示例程序。

    List list =session.createCriteria(StructuredCacheEntry.class)

                                //根据Student的属性进行过滤数据

                                .add(Restrictions.gt("name", "a"))

                                .list();

    在条件查询中,Criteria接口代表一次查询,该查询身不具备数据筛选,session调用createCriteria( Class clazz)方法对某个持久化类创建条件查询实例。

           Criteria对象并不具备任何数据筛选功能,但程序可以通过向 Criteria对象中组合多个Cri

    个 Criterion对象代表一个过滤条件)米实现数据过滤。

    Criteria包含如下两个方法

    Criteria setFirstResult(int firstResult)设置查询返回的第一行记录

    Criteria set MaxResults( int maxResults):设置查询返回的记录数

    这两个方法与 Query的两个类似方法的功能一样,都用于完成查询分页

    而 Criteria还包含如下常用方法

    Criteria add( Criterion criterion)h增加查询条件

    Criteria addOrder(Order order)增加排序规则

    List list():返回结果集

    Criterion接口代表一个查询条件,该查询条件由 Restrictions负责产生, Restrictions是专门用于产生查询条件的工具类,它的方法大部分都是静态方法,常用的方法如下

    1. static eq|ne|gt|ge|It|le( String propertyName. Object value):判断指定属性值是否等于|不等于|大于|等于|小于|小于等于指定值
    2. static eq|ne|gt|ge|It|leProperty( String propertyName, String otherPropertyName)判断第一个属性值(由propertyName参数确定)的值是否等于|不等于|大于|大于等于|小于|小于等于第二个属性(otherPropertyName参数确定)的值
    3. static Criterion allEq(Map propertyNameValues):判断指定属性(由Map参数的key指定)

    定值(由Map参数的vale指定)是否完全相等

    1. static Criterion between(String propertyName. Object lo. Object hi):判断属性值在某个值范
    2. static Criterion ilike( String propertyName, Object value):判断属性值匹配某个字符串(区分大小写)
    3. static Criterion ilike( String propertyName, String value, MatchMode matchMode判断属性值匹配某个字符串(不区分大小写),并确定匹配模式,
    4. static Criterion like(String propertyName, Obiect value)::判断属性值匹配某个字符串(区分
    5. static Criterion like(String propertyName, String value, MatchMode matchMode)判断属性值匹配某个字符串(区分大小写),并确定匹配模式
    6. Static Criterion in( String propertyName, Collection values):判断属性值在某个集合内匹配模式
    7. static Criterion in(String propertyName, Object[] values):判断属性值是数组元素的其中之一
    8. static Criterion isEmpty( String propertyName):判断属性值是否为空
    9. static Criterion isNotEmpty( String propertyName)判断属性值是否不为空
    10. static Criterion isNotNull( String property Name):判断属性值是否为空
    11. static Criterion isNull( Suing propertyName)判断属性值是否不为空
    12. static Criterion not( Criterion expression)t对 Criterion求否
    13. statie Criterion sizeEq(String propertyName, int size),判断某个属性的元素个数是否与size相等。
    14. static Criterion sqlRestriction( String sql):直接使用SQL语句作为筛选条件
    15. statie Criterion sqlRestriction( String sql. Object values. Type[] types):直接使用带参数占位符的SQL语句作为条件,并指定多个参数值
    16. static Criterion sqIRestriction( String sql. Object value. Type type):直接使用带参数占位符的SQL语句作为条件,并指定参数值
    17. Order实例代表一个排序标准,Oder有如下静态方法

    1>static Order asc( String property Name):根据 propertyName属性升序排序

    2>static Order desc( String property Name):根据 propertyName属性降序排序

    关联和动态关联

    如果需要使用关联实体的属性来增加查询条件,则应该对属性再次使用 createCriteria()方法。createCriteria()方法有如下重载版本

    1. Criteria createCriteria( String associationPath):使用默认的连接方式进行关联
    2. Criteria createCriteria( String associationPath, Join Type joinType):以 CoinType指定的连接方式(支持 INNER_JOIN、 LEFT_OUTER_JOIN、 RIGHT_OUTER_JOIN、 FULL_JOIN等枚举值)进行
    3. Criteria createCriteria( String associationPath, String alias):该方法的功能与上面第1个方法的功能基本相似,只是该方法允许为关联实体指定别名。
    4. Criteria createCriterial( String associationPath, String alias, JoinType joinType):该方法的功能与上面第2个方法的功能基本相似,只是该方法允许为关联实体指定别名
    5. Criteria createCriteria(String association Path, String alias, Join Type join Type, Criterion withclause):该方法的功能最强大,该方法既可为关联实体指定别名,也可指定连接类型,还可通过 with Clause指定自定义的连接条件一这可用于实现非等值连接。

    对比上面两个方法,不难发现两个方法的功能基本相似,只是第二个方法能显式指定连接方式

    使用别名

    createAlias()的重载的版本

    1. Criteria createAlias( String association Path, String alias):该方法的功能基本等同于

    create Criteria( String association Path, String alias)

    1. Criteria createAlias(String association Path. String alias, Join Type join Type)该方法的功能基本等同于Criteria createCriteria(String associationPath, String allias, JoinType joinType)
    2. Criteria createAlias(String associationPath, String alias, JoinType joinType, Criterion withClause)该方法的功能基本等同于Criteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause)

    List list2 = session.createCriteria(Person.class)

                                //此处添加限制条件必须是Person实体中存在 的属性

                                .add( Restrictions.gt("person_id", 1))

                                /****

                                 *  如果要增加对Person的关联类 的限制 则必须重新 createCriteria()

                                 * 如果此关联属性是集合,则只要集合中任意一个对象的属性满足下面条件即可,这里enrolements是person的关联实体, semester是enrolements的属性

                                 **/

                                .createCriteria("enrolements")

                                .add(Restrictions.gt("semester", 2))

                                .list();

    ç=====è

    List list3 = session.createCriteria(Person.class)

                                .add( Restrictions.gt("person_id", 12))

                                .createAlias("enrolments", "en")

                                .add( Restrictions.gt("en.semester", 2))

                                .list();

    延迟加载策略处理

    在默认情况下,条件查询将根据持久化注解指定的延迟加载策略来加载关联实体,如果希望在条件查询中改变延迟加载策略(就像在HQL查询中使用 fetch关键字一样),则可通过criteriade 的 setFetchModal()方法来实现,该方法也接受一个 FetchMode枚举类型的值, Fetch Mode支持如下枚举值

    1. DEFAULT:使用配置文件指定延迟加载策略处理
    2. JOIN:使用外连接、预初始化所有的关联实体
    3. SELECT启用延迟加载,系统将使用单独的 select语句来初始化关联实体,只有当真正间关联实体的时候,才会执行第二条 select语句

    如果想让程序在初始化 Student对象时,也可以初始化 Student关联的 Enrolment实体,则可使用如查询方法

    List list4 = session.createCriteria(Student.class)

                                //此处增加限制条件必须是Student实体存在的属性

                                .add( Restrictions.gt("studentNumber", 1) )

                                .setFetchMode("enrolments", FetchMode.JOIN)

                                .list();

    投影、聚合、分组

    在Pojections具类中提供了如下几个静态方法。

    1. AggregateProjection avg( String propertyName):计算特定属性的平均值。类似于avg函数
    2. CountProjection count( String propertyName):统计查询结果在某列上的记录条数,类似于count( column)函数。
    3. CountProjection countDistinct( String propertyName):统计查询结果在某列上不重复的记录条数。类似于 count(distinct colum)函数。
    4. PropertyProjection groupProperty( String propertyName):将查询结果按某列上的值进行分组,类似于添加group by字句

    以于添加 group by子句。

    1. aggregateProjection max( String propertyName):统计查询结果在某列上的最大值,类似于max函数
    2.  AggregateProjection min( String propertyName):统计查询结果在某列上的最小值。类似于min函数

    7. Projection rowCount():统计查询结果的记录条数。类似于 count()的功能。

    8.  AggregateProjection sum( String propertyName):统计查询结果在某列上的总和。类似于sum函数。

    下面的程序示范了如何通过投影运算来进行分组,使用聚集函数功能。

    List list5 = session.createCriteria(Enrolments.class)

                                .createAlias("student", "s")

                                .add(Projections.rowCount())

                                .add(Projections.max("s.name"))

                                .add(Projections.groupProperty("course")) //按course进行分组

                                .list();

    9.使用Projects的alias()方法为指定投影指定别名【为Projection指定别名】

    List list6 = session.createCriteria(Enrolments.class)

                                .createAlias("student", "s")

                                .add(Projections.alias(Projections.rowCount(), "c"))  //统计记录条数,并为统计结果指定别名

                                .addOrder(Order.asc("c")).list();

    10. 使用SimpleProjection的as()方法为自身指定别名【如果条件查询所使用的投影运算时SimpleProjection及其子类,可直接使用该投影对象的as()方法】

    List list7 = session.createCriteria(Enrolments.class)

                                .setProjection(Projections.projectionList()

                                //按course进行分组,并为分组结果指定别名

                                .add(Projections.groupProperty("course").as("c"))

                                //统计记录条数

                                .add(Projections.rowCount()))

                                。addOrder(Order.asc("c"))

                                .list()

    11. 使用ProjectList的add方法添加投影时指定别名

    List list8 = session.createCriteria(Enrolments.class)

                                .setProjection(Projections.projectionList()

                                              .add(Projections.groupProperty("course"), "c")

                                              .add(Projections.rowCount(),"rc"))

                                .addOrder(Order.asc("rc"))

                                .list();

    12. Property执行投影运算   【返回指定属性的集合】

    List list9 = session.createCriteria(Enrolments.class)

                                .setProjection(Property.forName("name"))

                                .list();

    13. 使用ProPerty根据指定列来过滤记录

    List list10 = session.createCriteria(Enrolments.class)

                                .createAlias("student", "s")

                                .setProjection(Projections.projectionList()

                                              .add(Property.forName("sourse"))

                                              .add(Property.forName("s.name"))

                                              .add(Property.forName("s.name").eq("指定名字"))

                                              )

                                .list();

    14.离线查询和子查询

    条件查询的离线查询有DetachedCriteria创建,允许在Session范围之外创建查询,任意session可以执行它。当吧DetaichedCriteria传入Criteria中作为查询条件时,就变为子查询

    //创建指定持久化类的离线查询

    DetachedCriteria.forClass(Class entity)

    //执行连线查询

           void datached() {

                  //定义一个离线查询

                  DetachedCriteria query = DetachedCriteria.forClass(Student.class)

                                .setProjection(Property.forName("name"));

                                //打开Session和事务

                                Session session = HibernateUtil.getSession();

                                Transaction txTransaction = session.beginTransaction();

                                //执行离线查询

                                List list = query.getExecutableCriteria(session).list();

                               

                                HibernateUtil.closeSession();

           }

           //执行子查询

           private void subQuery() {

                  //定义离线查询

                  DetachedCriteria subQuery = DetachedCriteria.forClass(Student.class)

                                .setProjection(Property.forName("name"));

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  //执行子查询

                  List list = session.createCriteria(Student.class)

                                //下面两行 具有同等作用

                                .add( Property.forName("name").in(subQuery))

                                .add(Subqueries.propertyIn("name", subQuery))

                                .list();

                 

           }

    Hibernate执行SQL查询

    SQL查询是通过SQLQuery接口来实现的,SQLQuery是Query的子接口。命名SQL查询还可以调用存储过程。

           Query接口方法:setFirstResult():     setMaxResult():     list():

    SQLQuery接口的方法:addEntity()  adddScalar():

    调动方法:

    1.创建查询对象:session.createSQLQuery()

    2.调用SQLQuery对象的addScalar()或addEntity()方法将选出的结果与标量值或实体进行关联,分别用于进行标量查询或实体查询

    3.调用Query的setXxx()方法为参数赋值

    4.调用Qeury的list()方法或uniqueResult()方法返回查询的结果集。

    标量查询

    //标量查询----返回有Object数组(Object[])组成的List Hibernate通过ResultSetMetadata来判定数据列表的实际顺序和类型

    session.createSQLQuery(“select * from student_inf”).list()

    //明确指定返回值类型通过addScalar()方法实现

    session.createSQLQuery(“select *from student_inf”).

    .addScalar(“name”, StandardBasicTypes.STRING)

    llist();

    //不指出数据类型

    session.createSQLQuery(“select *from student_inf”).

    .addScalar(“name”).list();

    实体查询

    将标量查询结果转换为实体

    单个实体的查询

    public void entityQuery() {

                  //打开Session和事务

                  Session session  = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  String sqlString = "select * from enrolments_inf where year=?1";

                  List list = session.createSQLQuery(sqlString)

                                //指定将查询的纪录行转换为实体

                                .addEntity(Enrolments.class)

                                ////为SQL的字符串的参数赋值

                                .setInteger("1", 2)

                                .list();

           }

    执行返回多个实体的SQL查询

    如果sql语句中显式使用了多表链接,则SQL语句可以选择出多个数据表的数据。则SQL字符串中应为不同的数据表指定不同的别名,并调用addEntity(String alias, Calss entityClass)方法将不同的数据表转换为成不同的实体。

    public void multiEntityQuery() {

                  //打开Session和事务

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  String sqlString = "select s.*,e.*,c.*"

                  + "from strudent_inf s, enrolemnt_inf e, couuse_inf c"

                  + "and e.course_code = c.course_code";

                  List list = session.createSQLQuery(sqlString)

                                //指定将从s表查询得到的纪录行转换成Student实体

                                .addEntity("s", Student.class)

                                //指定将从e表查询得到的纪录行转换为成Enrolment实体

                                .addEntity("e",Enrolments.class)

                                //

                                .addEntity("c", Course.class)

                                .list();

                  //提交事务,关闭Session

                  txTransaction.commit();

                  HibernateUtil.closeSession();

           }

    把查询结果转换为非持久化使体,只要这些javaBean为这些数据列提供getter和setter方法,Query接口提供了一个setResultTransformer()方法,该方法接受一个Transformers对象,使用该对象可把查询结果转换成javaBean集

    String sqlString = "select s.name stuName,c.name courseName"

                                + "from student_inf s, enrolment_inf e,course_inf c"

                                + "where s.student_id = e.student_id"

                                + "and e.course_code = c.course_code";

                  List list = session.createSQLQuery(sqlString)

                                //指定将查询的记录行转换成StudentCourse对象

                                .setResultTransformer(Transformers.aliasToBean(StudentCourse.class))

                                .list();

    处理关联和继承

    将关联实体转换成查询结果:使用SQLQuery adjoin(String alias, String path)方法

    alias转换后的实体名          path待转换的实体属性

    //使用关联的原生SQL查询

           public void joinQuery() {

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  String sqlString = "select s.*, e.* from student_inf s, "

                                + "enrolemnts_inf e where s.student_id=e.student_id";

                  List list = session.createSQLQuery(sqlString)

                                .addEntity("s", "s.enroments")

                                .addJoin("e", "s.enrolments")

                                .list();

           }

    命名SQL查询

    原生SQL查询

    @NamedNativeQuery 定义单个原生

    @NamedNativeQueries注解,用于组合多个命名的原生SQL查询

                                @NamedNativeQuery支持的属性

    属性

    是否必须

    说明

    name

    指定命名的原生SQL查询的名称

    query

    指定该原生SQL查询的查询字符串

    resultClass

    属性指定一个实体类的类名,用于将查询结果集映射成该实体类的实例

    resultSetMapping

    该属性指定一个SQL结果映射【使用SqlResultSetMapping】的名称,用于指定使用该SQL结果集映射来转换查询结果集

    @SqlResultSetMapping 指定的属性

    属性

    是否必须

    说明

    namer

    指定SQL结果映射的名称

    columns

    该属性的值为@ColunnResult注解数组,每个@ColumnResult注解定义一个标量查询

    entities

    该属性的值为@EntityResult注解定义一个实体查询

    classes

    该属性的值为@ConstructorResult注解数组,每个@ConstructorResult负责将指定的多列转换为普通类(非持久化类)的对应属性

    1单个实体

    //将查询得到的结果转换为student实体

           @NamedNativeQuery(name="simpleQuery"

                         //指定命名SQL查询对应的SQL语句

                         ,query = "select s.student_id, s.name from student_inf s"

                         //指定将查询结果转换为Student实体

                         ,resultClass=Student.class)

           //将查询结果转换成多个实体,而且同时进行标量查询,实体查询

    2.多个实体的查询

           @NamedNativeQuery(name="queryTest"

                         ,query="select s.*, e.*,c.* from student_inf s,enroments_inf e,"

                         +"courser_inf c where s.student_id - e.student_id and"

                                       + "e.courser_code = c.course_code and e.year=:targetYear"

                         //指定使用名为firstMapping的@SqlResultSetMapping完成结果映射

                                       ,resultSetMapping = "firstMapping")

    //    同时使用@SqlResultSetMapping

           @SqlResultSetMapping(name="firstMapping",entities= {@EntityResult(entityClass = Student.class),

                         @EntityResult(entityClass=Enrolment.class),

                         @EntityResult(entityClass=Course.class, fields= {

                                       @FieldResult(name="courserCode",column="c.course_code"),

                                       @FieldResult(name="name",column="c.name")

                         })}

           ,columns=(@ColumnResult(name="s.name",type = String.class)))

    //    使用示例

           private void query() {

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  //

                  List list = session.getNamedQuery("queryTest")

                                .setInteger("targetYear", 2009)

                                .list();

                  txTransaction.commit();

                  HibernateUtil.closeSession();

                  for(Object ele :list)

                  {

                         //每个集合的元素是Student、Enroments、和stuName三个元素的数组

                         Object[] objects = (Object)ele;

                         Student student = (Student)objects[0];

                         Enrolments enrolments = (Enrolments)objects[0];

                         Course course = (Course)objects[2];

                         String stuName = (String)objs[3];

                        

                  }

           }

    调用存储过程

    创建存储过程[无法使用分页查询]

    create procedure select_all_student() select * from student_inf

    //定义一个调用存储过程的命名SQL查询

           @NamedNativeQuery(name="callProcedure",

                         query="{call select_all_student()}"

                         ,resultSetMapping="secondMapping")

           @SqlResultSetMapping(name = "secondMapping",entities= {@EntityResult(entityClass=Student.class,

                                              fields= {

                                                            @FieldResult=(name="studentNumber", column="student_id"),

                                                            @FieldResult(naem = "name", column="name")

                                              })

           })

           //调用存储过程

           private void callProdedure() {

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  //

                  List list = session.getNamedQuery("callProcedure")

                                .list();

                  txTransaction.commit();

                  HibernateUtil.closeSession();

           }

    Hibernate定制SQL的使用

    注解:

    @SQLInsert: 定制插入记录的SQL语句

    @SQLUpdate: 定制更新记录的sql语句

    @SQLDelete  定制删除记录的sql语句

    @SQLDeleteAll: 定制删除所有记录的SQL语句

    //定制insert的sql语句

    @SQLInsert(sql="insert into news_inf(contetn,title) values(upper(?),?)")

    //定制update的sql语句

    @SQLUpdate(sql="update news_inf set content=upper(?), title=? where news_id=?")

    //指定delete的sql语句

    @SQLDelete(sql="delete from news_inf where news_id=?")

    //定制删除所有实体的sql语句

    @SQLDeleteAll(sql="delete from news_inf")

    //使用存储过程

    @SQLInsert(callable = true, sql="{call createPerson (?, ?)}")

    @SQLDelete(callable = true, sql="{ ? = call deletePerosn (?)}")

    @SQLDelete(callable = true, sql="{? = call updatePerson (?, ?)}")

    //查询指定实体  指定使用news_loader命名查询作为定制查询的语句

    @Loader(namedQuery = "news_loader")

    //定义一个命名sql查询

    @NamedNativeQuery(name="news_loader", query= "select news_id, contat('---', concat(title,'===')) as title"

    +",content from news_inf n where news_id =?"

                  ,resultClass= News.class)

    数据过滤

    过滤器的使用

    系统默认不开启过滤器,必须通过Session的enableFilter(String filterName)才可以启用过滤器,该方法返回一个Filter实例,Filter包含setParameter()方法用于为过滤器参数赋值。

           一旦启用了过滤器,过滤器就在整个Session内有效,所有的数据加载将自动调用该过滤条件,直到调用disableFilter()方法

    1定义过滤器。使用 Hibernate提供的@ FilterDef注解定义过滤器,如果需要定义多个过器,如果定义多个过滤器,需使用@ FilterDefs注解来组合多个@ Filter Def.

    2 使用过滤器。使用@ Filter元素应用过滤器。

    3 在代码中通过 Session启用过滤器。

    上面注解中的@ FilterDef通常用于修饰持久化类,用于定义注解;@Filer则通常用于类或集合属性(包括关联实,表示对指定持久化类或集合属性(包括关联实体)应用过器

           一个持久化类或集合可以使用多个过滤器,而一个过滤器也可以作用于多个持久化类或集会(包括关联实体)。

    使用@ FilterDef时可指定如表所示的属性

    属性

    是否必须

    说明

    name

    指定过滤器名称

    defaultCondition

    该属性的值为带参数的sql条件表达式,用于指定该过滤器默认的过滤条件

    parameters

    该属性指定过滤器中sql条件表达式指定的参数

    从上面介绍可以看出,@ FilterDef的主要作用是定义过滤器,定义过滤器只是指定该过滤器名称,并指定该过滤条件所支持的参数—至于过滤条件,定义过滤器时可以无须指定,完全可以等到应用该滤器时,使用@ Filter注解指定

    @FilterDefs({

           //定义名为effectiveDate的过滤器,该过滤器支持date类型的参数

           @FilterDef(name="effectiveDate", parameters= {@ParamDef(name="asOfDate", type="date"})}),

           //定义名为category的过滤器,该过滤器支持一个Int类型的过滤器

           @FilterDef(name="category",parameters= {@ParamDef(name="catId",type="int")})

          

    })

    @Entity

    @Table(name="product_inf")

    //使用effectiveDate过滤器对product实体使用数据过滤器

    @Filter(name="effectiveDate", condition=":asOfDate BETWEEN eff_start_date AND eff_end_date")

    public class Product {

           //定义开始时间

           @Column(name="eff_start_date")

           private Date effectiveStartDate;

           //定义失效时间

           @Column(name="eff_end_date")

           private Date efffectiveEndDate;

           //定义产品所属种类

           @ManyToMany(targetEntity=Category.class)

           @JoinTable(name="product_category"

           ,joinColumns=@JoinColumn(name="product_id")

           ,inverseJoinColumns=@JoinColumn(name="category_id"))

           //对关联实体的抓取使用effectiveDate、category进行数据过滤

           @Filters({

                  @Filter(name="effectiveDate", condition=":asOfDate BETWEEN eff_start_date and eff_end_date"),

                  @Filter(name="category", condition="category_id = :catId")

           })

                  private Set<Category> categories = new HashSet<>();

    }

    //启用过滤器

    //启动effectiveDate过滤器,并设置参数

           private void testFilter() throws Exception {

                  Session session = HibernateUtil.getSession();

                  Transaction txTransaction = session.beginTransaction();

                  //

                  List list = session.enableFilter("effectiveDate")

                                .setParameter("asOfDate", new Date(date));

                  //启动category过滤器,并设置参数

                  session.enableFilter("category")

                  .setParameter("carId", new Long(2));

                  //查询所有的Product,不加任何筛选条件,但effectiveDate过滤会起作用

                  txTransaction.commit();

                  HibernateUtil.closeSession();

           }

  • 相关阅读:
    Berry Jam(前缀后>差值,贪心)
    Privatization of Roads in Treeland (贪心+染色)
    主席树
    C 语言是一门抽象的、面向过程的语言,C 语言广泛应用于底层开发
    限流中间件AspNetCoreRateLimit
    远程调试 Visual Studio2022
    高并发下秒杀
    设计模式的分类和六大原则
    MySQL的锁机制
    代码是怎么运行
  • 原文地址:https://www.cnblogs.com/sundaysjava/p/10347431.html
Copyright © 2020-2023  润新知