Hibernate框架

来源:互联网 发布:剑三菊花插件dbm数据 编辑:程序博客网 时间:2024/06/08 05:26

Hibernate框架

1 hibernate是什么?

     hibernate是一个框架。

     hibernate是一个持久化框架。

     hibernate是一个封装了JDBC的持久化框架。

          以后使用hibernate不用写jdbc了,select ,insert , delete , update

     Hibernate是一个基于ORM的封装JDBC的持久化框架。

2 持久化?

     化--过程。

     程序中的数据是临时。

     将程序中临时性的数据持久的保存起来的过程。叫持久化。

     1数据库---jdbc

     2文件操作---io

3 ORM?

     对象关系映射

     对象:java程序中类

     关系:关系型数据库中的表

O;

public class Goodsimplements java.io.Serializable {

     // Fields

     private Integer goodsId;

     private String goodsName;

     private Double goodsPrice;

     private Integer goodsNum;

R:

CREATE TABLE goods (

  goods_id int(11) NOT NULL auto_increment,

  goods_name varchar(200) default NULL,

  goods_price double default NULL,

  goods_num int(11) default NULL,

  PRIMARY KEY  ('goods_id')

)

M:Goods.hbm.xml文件,ORM文件

<hibernate-mapping>

    <class name="com.no8.domain.Goods"table="goods"catalog="hibernate">

        <id name="goodsId"type="java.lang.Integer">

            <column name="goods_id" />

            <generator class="identity"></generator>

        </id>

        <property name="goodsName" type="java.lang.String">

            <column name="goods_name" length="200" />

        </property>

        <property name="goodsPrice" type="java.lang.Double">

            <column name="goods_price" precision="22" scale="0" />

        </property>

        <property name="goodsNum" type="java.lang.Integer">

            <column name="goods_num" />

        </property>

    </class>

</hibernate-mapping>

 

 

4 手动实现Hibernate的第一个案例(基于hibernate4.3.5版本)

4.1 创建工程并导入hibernate的jar文件


4.2 编写实体类和数据库关系表

public class Goodsimplements java.io.Serializable {

     // Fields

     private Integer goodsId;

     private String goodsName;

     private Double goodsPrice;

     private Integer goodsNum;

CREATE TABLE goods (

  goods_id int(11) NOT NULL auto_increment,

  goods_name varchar(200) default NULL,

  goods_price double default NULL,

  goods_num int(11) default NULL,

  PRIMARY KEY  ('goods_id')

)

4.3 编写ORM文件

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

     <class name="com.no8.domain.Goods"table="goods">

         <id name="goodsId"column="goods_id">

              <generator class="identity" />

         </id>

         <property name="goodsName" type="java.lang.String" column="goods_name" />

         <property name="goodsPrice" type="java.lang.Double" column="goods_price" />

         <property name="goodsNum" type="java.lang.Integer" column="goods_num" />

     </class>

</hibernate-mapping>

4.4 编写Hibernate的配置文件-hibernate.cfg.xml

     在工程的src目录下创建一个名称为hibernate.cfg.xml的XML文件

<?xml version='1.0'encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

 

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="connection.url">jdbc:mysql://127.0.0.1:3306/no8?useUnicode=true&amp;characterEncoding=utf8</property>

        <property name="connection.username">root</property>

        <property name="connection.password">root</property>

        <!-- 方言 -->

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 显示Hibernian生成的SQL语句 -->

        <property name="show_sql">true</property>

        <!-- 加载ORM映射文件 -->

        <mapping resource="com/no8/domain/Goods.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

4.5 编写工具类加载Hibernate配置文件创建sessionFactory

基于hibernate4版本。在hiberante3版本中不要修改

Configuration configuration = new Configuration().configure();

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()

         .applySettings(configuration.getProperties()).build();

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

4.6 从SessionFactory中创建Session对象

Session session = HibernateUtil.getSessionFactory().openSession();

4.7 通过调用session对象的方法实现数据库的CURD操作

public class SaveTest {

     public staticvoid main(String[] args) {

         Goods goods = new Goods();

         goods.setGoodsName("索爱");

         goods.setGoodsNum(1);

         goods.setGoodsPrice(35D);

         Session session = HibernateUtil.getSessionFactory().openSession();

         Transaction tran = session.getTransaction();

         tran.begin();

         session.save(goods);

         tran.commit();

         session.close();

         HibernateUtil.getSessionFactory().close();

         System.out.println("end");

     }

}

public class FindById {

     public staticvoid main(String[] args) {

         Session session = HibernateUtil.getSessionFactory().openSession();

         Goods goods = (Goods) session.get(Goods.class, 3);

         session.close();

         System.out.println(goods.getGoodsName());

         System.out.println(goods.getGoodsPrice());

         System.out.println("end");

     }

}

public class Update {

     public staticvoid main(String[] args) {

         Session session = HibernateUtil.getSessionFactory().openSession();

         Goods goods = (Goods) session.get(Goods.class, 3);

         goods.setGoodsNum(100);

         Transaction tran = session.getTransaction();

         tran.begin();

         session.update(goods);

         tran.commit();

         session.close();

         System.out.println("end");

     }

}

public class Delete {

     public staticvoid main(String[] args) {

         Session session = HibernateUtil.getSessionFactory().openSession();

         Goods goods = (Goods) session.get(Goods.class, 3);

         Transaction tran = session.getTransaction();

         tran.begin();

         session.delete(goods);

         tran.commit();

         session.close();

         System.out.println("end");

     }

}

public class FindAll {

     public staticvoid main(String[] args) {

         String hql ="from com.no8.domain.Goods";

         Session session = HibernateUtil.getSessionFactory().openSession();

         Query query = session.createQuery(hql);

         List<Goods> goodsList = query.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName()+":"+goods.getGoodsPrice());

         }

         session.close();

        

         System.out.println("end");

     }

}

 

5 Hibernate中核心类和接口

5.1 Session接口

     hibernate框架最核心的接口,所有操作数据库的方法都是这个对象的方法。

     session.save()   session.update()   session.delete()   session.get() session.load()

5.2 SessionFactory工厂类

     hibernate框架中的session工厂,负责生成session对象。

     生产的session对象由Hibernate.cfg.xml文件中配置信息决定的。

     sessionFactory.openSession();

5.3 Configuration类

     负责读取Hibernate.cfg.xml文件的类

5.4 Transaction事务对象

     进行数据库增删改操作时要使用事务,就是hibernate中的事务对象

     Transactiontran = session.getTransaction();

     tran.begin()  tran.commit() tran.rollback()

5.5 Query接口

     Query接口是一个在hibernate中执行查询语句hql语句的一个接口。

     Queryquery = session.createQuery("hql语句");

 

6 使用MyEclipse工具创建第一个Hibernate案例

6.1 创建工程

6.2 在MyEclipse中创建一个数据库的连接


6.3 为工程加入hibernate框架

针对MySql数据库中文乱码的配置

<propertyname="connection.useUnicode">true</property>

<propertyname="connection.characterEncoding">UTF-8</property>

6.4 使用工具反向生成实体类和ORM文件

     换到database面板-->数据表名上右键-->Hibernate....

6.5 编写Service

public class GoodsService {

     private GoodsDAO goodsDAO = new GoodsDAO();

     public boolean save(Goodsgoods) {

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         try {

              tran.begin();

              this.goodsDAO.save(goods);

              tran.commit();

              return true;

         } catch (Exception e) {

              e.printStackTrace();

              tran.rollback();

              return false;

         }

     }

}

 

7 Hibernate的配置文件-hibernate.cfg.xml

7.1 使用连接池C3P0

     1导入C3P0连接池的jar文件

手动编写工程时使用jar位置

使用工具自动方式

     2在hibernate.cfg.xml文件中配置c3p0的相关设置

7.2 show_sql和format_sql属性

     show_sql= true|false  表示显示Hibernate生成的sql语句

     format_sql= true|false 表示是否格式化显示的sql语句

8 使用log4j日志显示更详细的信息

     project-etc-log4j.properties

log4j.logger.org.hibernate.type=trace

 

 

9 ORM文件

9.1 动态插入和动态更新

在ORM文件中的<class节点上的二个属性

<class   dynamic-insert="false"dynamic-update="false">

dynamic-insert="true|false"动态插入,true表示启动动态插入

dynamic-update="true|false"动态更新

 

动态插入:dynamic-insert="true"

当对象的属性值为null时,将不会在生成的sql语句中出现对应字段的插入。

 

     数据库表结构:加入了一个带有系统当前时间做为默认值的日期时间字段

goods_date字段有默认值,在程序中用不用赋值?不用。在程序中默认值为null


当我们保存Goods时,没有设置动态插入:dynamic-insert="false"

所以在数据库的记录上goods_date字段的值为null.

当我们保存Goods时,有设置动态插入:dynamic-insert="true"

在生成的sql语句中没有goods_date字段,

所以在数据库表中的记录上goods_date字段的值用数据库的默认值。

 

动态更新:dynamic-update="true"

     当对象的属性没有发生变化时,在Hibernate生成的update语句中不会出现相对应的字段的修改。

     update表名 set 字段=值,字段=值 where 条件;

 

dynamic-update="true"

     public staticvoid main(String[] args) {

         // TODO Auto-generated method stub

         GoodsService goodsService = new GoodsService();

        

         Goods goods = goodsService.findById(15);

        

         goods.setGoodsPrice(goods.getGoodsPrice()*0.8);

        

         goodsService.update(goods);

        

         System.out.println("end");

     }

 

10 延迟加载 <classlazy="true|false"

     加载在hibernate应用中表示从数据库中查询数据。

    

     英:lazy   中:懒

     lazy="true"时延迟加载

 

     延迟加载 : 就是等一会再查询数据,不用不查询,当使用查询对象的非主键字段时才会向数据库发送查询语句。

 

10.1 延迟加载的条件

     只有在同一个会话没有关闭的时候,延迟加载才能正常使用。

         Session session = HibernateSessionFactory.getSession();

         Goods goods = (Goods)session.load(Goods.class, 1);

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

         System.out.println(goods.getGoodsName());

         System.out.println(goods.getGoodsPrice());

         System.out.println("end");

     第一次使用goods对象的属性是goods.getGoodsName(),但是在使用这个方法之前已经closeSession了。

     如果会话已经关闭,再使用延迟加载则会发生以下的异常:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

 

11 延迟加载对WEB应用程序的影响

关闭在延迟加载之前,所以程序会在goods.jsp页面上报出异常,

LazyInitializationException: could not initialize proxy - no Session

 

使用过滤器对响应进行过滤,在过滤时关闭session。

创建一个关闭会话的过滤器。OpenSessionInViewFilter.java

 

GoodsService

不能再在业务层关闭会话对象了。

public class GoodsService {

     private GoodsDAO goodsDAO = new GoodsDAO();

     public Goods findById(Integer id) {

         return this.goodsDAO.findById(id);

     }

     public List<Goods> findAll() {

         return this.goodsDAO.findAll();

     }

}

OpenSessionInViewFilter

public class OpenSessionInViewFilterimplements Filter {

     public void doFilter(ServletRequestrequest, ServletResponse response,

              FilterChain chain) throws IOException, ServletException {

         chain.doFilter(request,response);

         HibernateSessionFactory.closeSession();

     }

     <filter>

         <filter-name>opensession</filter-name>        

         <filter-class>com.no8.filter.OpenSessionInViewFilter</filter-class>

     </filter>

     <filter-mapping>

         <filter-name>opensession</filter-name>

         <url-pattern>*.do</url-pattern>

     </filter-mapping>

 

12主键生成策略generator

     在每个实体类的映射中都有一个主键的映射

     <class>          实体类映射

         <id>         主键映射

              <generatorclass="identity"></generator>   主键生成策略

         </id>

     </class>

11.1 increment自增长。按主键字段最大值+1的方式实现主键生成的策略

Hibernate: select max(goods_id) from goods

Hibernate: insert into hibernate.goods (goods_name, goods_price, goods_num, goods_id) values (?, ?, ?, ?)

保存成功!

11.2 identity标识列,针对mysql数据库。

11.3 native 自动,让Hibernate自己看着办

11.4 assigned 手动设置,由程序说了算。

11.5 sequence序列,针对Oracle数据库。

oracle数据库中的表

oracle数据库中的序列对象

ORM映射文件:

     在主键映射信息中的主键生成策略:

     <generatorclass="sequence"></generator只能表示使用序列,但用哪个序列对象没有,默认hibernate_sequence

     在oracle数据库中有一个叫"MYSEQ"的序列。指明使用这个序列对象

<generator class="sequence">

     <paramname="sequence">MYSEQ</param>

</generator>

     生成的sql语句

Hibernate: select MYSEQ.nextval from dual

Hibernate: insert into NO8.GOODS (GOODS_NAME, GOODS_PRICE, GOODS_NUM, GOODS_TYPE, GOODS_ID) values (?, ?, ?, ?, ?)

end

 

13 对比SessionFactory中两种获得Session的方式

13.1 在使用SessionFactory获得session的方式有两种

         SessionFactory sf = HibernateSessionFactory.getSessionFactory();

         //第一种从sf中获得session的方式

         Session session1 = sf.openSession();

         //第二种从sf中获得session的方式

         Session session2 = sf.getCurrentSession();

13.2 openSession()

     这是一个很单纯的方法,每调用一次就从sf中获得一个新的会话(Session)对象。

     程序中对于openSession方法的使用需要配置合其他代码。才能事务的完整。

     为了保存在Hibernate中事务的完整,必须使用同一个会话对象,所以使用openSession时要配合ThreadLocal<Session>

 

13.3 getCurrentSession()

     这是一个获得当前线程中的会话对象的方法。

     在Hibernate框架中已经对会话对象进行了管理,也会有本地线程对象保存会话对象,

     getCurrentSession方法可以从当前线程中获得会话对象

     所以为了事务的完整,在使用getCurrentSession方法时不用配合其他类的使用。

13.3.1 注意一:必须在Hibernate.cfg.xml中有相关设置

HibernateException: No CurrentSessionContext configured!

在Hibernate.cfg.xml文件中加入如下配置信息:

<property name="current_session_context_class">thread</property>

13.3.2 注意二:必须在事务环境下执行

HibernateException: get is not valid without active transaction

13.3.3 注意三:会话对象不能再手动关闭

使用getCurrentSession时,当事务进行提交或回滚操作时会自动关闭会话对象。

SessionException:Session was already closed

14 对于session的get和load方法

     get方法和load方法都是按主键查询的方法

     get方法表示获得一个对象。

     load方法表示加载一个对象。

14.1 get方法

     get方法表示获得一个对象,

     get方法不会参考<class lazy的设置,都是立即加载类对象。

     get方法返回的对象的类型就是对象本身的类型

14.2 load方法

     load方法表示加载一个对象

     load方法会参考<class lazy的设置,当lazy="true"时使用延迟加载 。

     load方法返回的对象的类型是一个代理对象。代理了Goods对象原有的功能的同时附加了新的功能。

 

14.3 代理模式的第一个演示

public class ProxyGoodsextends Goods {

     @Override

     public String getGoodsName() {

         System.out.println("查询数据库!");

         return super.getGoodsName();

     }

}

Goods g = new ProxyGoods();

g.setGoodsName("刘洁");

System.out.println(g.getGoodsName());

15 持久化对象的三种状态

     持久化类:一个对后台数据库中表有映射关系的类。

     Goods.java      Goods.hbm.xml文件

     Goods这个类就是持久化类。

     持久化对象:持久化类的实例。

     Goodsgoods = new Goods(); goods就是持久化对象。

 

     一个持久化对象一共有三种状态:

     1临时态transient

     2 持久态persistent

     3 脱管态detached

15.1 区分三种状态

                                 id(是否有主键值)      session(是否有打开的会话对对象进行管理)

     临时态transient          null                        没有session

     持久态persistent        非空,有记录             有session

     脱管态detached          非空                       没有session

 

     一个保存商品的过程。

Goods goods = new Goods();//临时状态对象goods

goods.setGoodsName("清风");

goods.setGoodsPrice(2D);

goods.setGoodsNum(10);

 

Session session = HibernateSessionFactory.getSession();

 

Transaction tran = session.getTransaction();

tran.begin();

session.save(goods);//保存成功之后,持久状态的goods

tran.commit();

HibernateSessionFactory.closeSession();

 

System.out.println(goods.getGoodsName());//session关闭之后,脱管状态的goods对象

15.2 持久状态对象对数据库的影响

     持久状态对象特点,与数据库保持连接,同时数据库中有一条记录与对象对应。

     持久状态对象的修改等直接修改数据库中对应的记录。

     持久状态对象就是关联着一个记录,对持久状态对象属性的修改就是对记录的修改。

15.3 三种状态之间的变化规律

 

 

16 单表的HQL语句

     进行数据库的查询,

     1get

     2load

     3DAO.findall()-hql语句

16.1 hql是什么?

     hql是hibernate查询语句,语法与sql基本一致

     hql与sql最大的不同,hql语句是一个针对类进行查询语句。

     hql语句是一种面向对象的查询语句。

16.2 Query接口

     org.hibernate.Query

     Query接口是在Hibernate中执行hql语句的接口。

     当我们想使用hql语句进行查询时必须先获得Query接口的实例。

16.3 获得Query接口的实例

     Queryquery = session.createQuery("hql语句");

16.4 使用Query接口的方法查询数据库记录

     使用Query接口的方法进行数据库查询,面向对象的方式实现查询。

     1list() 返回一个查询的集合

         String hql = "from com.no8.domain.Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<Goods> goodsList = query.list();

         HibernateSessionFactory.closeSession();

        

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsId()+":"+goods.getGoodsName());

         }

     2uniqueResult()  返回一个查询的对象

         String hql ="from Goods where goodsId=95";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         Goods goods = (Goods) query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(goods.getGoodsId());

         System.out.println(goods.getGoodsName());

 

16.5 在hql语句中使用参数-?

     要hql语句中我们可以使用"?"的方式来增加参数。

     在执行hql语句时,使用Query接口的方法为参数赋值。

         String hql ="from Goods where goodsId=?";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         query.setInteger(0, 2);

         Goods goods = (Goods) query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(goods.getGoodsId());

         System.out.println(goods.getGoodsName());

16.6 在hql语句中使用参数,使用参数名(推荐)

     要hql语句中我们可以使用":参数名"的方式来增加参数。

     在执行hql语句时,使用Query接口的方法为参数赋值。

         String hql ="from Goods where goodsId=:goodsId";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         query.setInteger("goodsId", 4);

         Goods goods = (Goods) query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(goods.getGoodsId());

         System.out.println(goods.getGoodsName());

16.7 使用query接口的setProperties(Object)方法为参数赋值

from Goods  where goodsName like :goodsName and  goodsPrice between :min and :max

几个参数?3,goodsName,min,max

     创建一个保存查询条件值的实体类:

public class SearchVO {

     private String goodsName;

     private doublemin;

     private doublemax;

 

     在使用Query接口的setProperties(实体类的对象)

     Hibernate会自动将SearchVO类的属性的值与HQL语句中的参数对应,名称一致。

16.8 使用Hibernate实现多条件查询基于查询对象SearchVO

16.8.1 创建查询对象SearchVO

public class SearchVO {

     private String goodsName;

     private Double min;

     private Double max;

     private Integer goodsNum;

16.8.2 在DAO中编写一个多条件查询的方法find(SearchVO searchVO)

     public List<Goods> find(SearchVO searchVO){

         log.debug("finding all Goods instances");

         try {

              String queryString = "from Goods where 1=1 ";

              if(searchVO.getGoodsName() !=null ){

                   queryString+= "and goodsName like :goodsName ";

              }

              if(searchVO.getMax()!=null){

                   queryString+= "and goodsPrice <= :max ";

              }

              Query queryObject = getSession().createQuery(queryString);

              queryObject.setProperties(searchVO);

              return queryObject.list();

         } catch (RuntimeException re) {

              log.error("find all failed",re);

              throw re;

         }

     }

 

16.9 使用query接口的setProperties(Map)方法为参数赋值

     @Test

     public void query4() {

         String hql = "from Goods where goodsName like :goodsName and "

                   + "goodsPrice between :min and :max";

         Map<String, Object> map = new HashMap<String, Object>();

         map.put("goodsName","%");

         map.put("min", 10D);

         map.put("max", 100D);

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         query.setProperties(map);

         List<Goods> goodsList = query.list();

         HibernateSessionFactory.closeSession();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName() +":"

                       + goods.getGoodsPrice());

         }

         System.out.println("end");

     }

 

16.10 Hql语句也支持分页查询

     在Hibernate中分页的实现是通过调用Query接口的丙个方法实现的。

         query.setFirstResult(5);//当前查询时启始的索引

         query.setMaxResults(5);//查询的记录个数

         query.list();

 

16.11 hql的投影查询-select

     在hql语句中没有select *

     当我们只想查询某几列时,称投影查询,就要使用select 属性名,属性名

16.11.1 select goodsName,goodsPrice from Goods

     返回类型是一个List<Object[]>。

     hibernate会将每条记录做成一个Object[],数组中的第一个元素就是一行的每个属性。

     查询结构有多条记录时,就做集合将多个Object[]放到集合中。

 

     List<Object[]>list  = query.list();

16.11.2 可以利用类的创建方法修改返回类型

     0投影查询的hql语句

select new Goods(goodsName,goodsPrice) from Goods

     1在Goods类上,创建一个有参构造

    public Goods(String goodsName, Double goodsPrice) {

         super();

         this.goodsName =goodsName;

         this.goodsPrice =goodsPrice;

     }

     2接收时Hibernate就能够使用构造方法自动实体化为Goods类的实例。

     public void query7(){

         String hql = "select new Goods(goodsName,goodsPrice) from Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<Goods> goodsList = query.list();

         HibernateSessionFactory.closeSession();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName() +":"

                       + goods.getGoodsPrice());

         }

     }

 

16.12 Hql支持函数的使用

     sql聚合函数: sum , count,min , max ,avg

     sql语句: select count(*) from 表名

     hql语句: select count(*) from 类名

     public void query8(){

         String hql = "select count(*) from Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         Long o = (Long)query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(o);

     }

     public void query9(){

         String hql = "select sum(goodsPrice),min(goodsPrice),max(goodsPrice)"

                   + " from Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         Object[] objs = (Object[]) query.uniqueResult();

         HibernateSessionFactory.closeSession();

         for (Object object : objs) {

              System.out.println(object);

         }

     }

在Hql中可以使用map来优化函数的使用。

     public void query10(){

         String hql = "select"

                   + " new Map(sum(goodsPrice) as sum,min(goodsPrice) as min)"

                   + " from Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         Map<String,Double> map = (Map<String,Double>)query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(map.get("sum"));

         System.out.println(map.get("min"));

//       Map map = new HashMap();

//       map.put("name", "peter");

//       map.put("address", "北京");

//       System.out.println(map);

     }

 

     public void query11(){

         String hql = "select"

                   + " new com.no8.vo.GoodsSum(sum(goodsPrice),min(goodsPrice))"

                   + " from Goods";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         GoodsSum goodsSum = (GoodsSum) query.uniqueResult();

         HibernateSessionFactory.closeSession();

         System.out.println(goodsSum.getSum());

         System.out.println(goodsSum.getMin());

     }

public class GoodsSum {

     private Double sum;

     private Double min;

 

16.13 hql支持分组group by

     public void query12() {

         String hql = "select  count(*)   from Goods group by goodsName";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<Long> ls = query.list();

         HibernateSessionFactory.closeSession();

         for (Long long1 : ls) {

              System.out.println(long1);

         }

    

     @Test

     public void query13() {

         String hql = "select"

                   + " new Map(count(*) as count , sum(goodsNum) as sum)"

                   + " from Goods group by goodsName";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<Map> ls = query.list();

         HibernateSessionFactory.closeSession();

         for (Map map : ls) {

              System.out.println(map.get("count") +"=" + map.get("sum"));

         }

     }

     @Test

     public void query14() {

         String hql = "select"

                   + " new Map(goodsName as name,count(*) as count , sum(goodsNum) as sum)"

                   + " from Goods group by goodsName";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<Map> ls = query.list();

         HibernateSessionFactory.closeSession();

         for (Map map : ls) {

              System.out.println(map.get("name") +"=" + map.get("count") +"="

                       + map.get("sum"));

         }

     }

 

 

17 关联关系映射-单向多对一映射(基础)

     关联关系:在数据库表与表之间是有关系。在数据库两张表之间的关系维护的手段只有一个,“主外键约束”

     在Hibernate中也要能维护在数据库中的表与表之间的关联关系。

17.1 数据库中表的关系模型

     数据库中两张表:商品与类型

类型表:

商品表:

两张表在数据库中有没有关系?

有关系,在数据库使用外键的方式创建的关系。

在Goods表中有一个外键字段,引用Goods_type表。

 

在数据库中两张表有关系,产生关系字段,关系映射基数

     一个商品可以属于一个类型

     一个类型可以拥有多个商品

     所以我们把 商品->类型 的关系称为 多对一

                   类型->商品 的关系称为 一对多

 

     最终:Hibernate中关联关系映射-单向多对一映射,,表示我们只考虑从商品到类型的映射

17.2 Hibernate的生成的实体类与ORM文件

17.2.1 先生成类型Goods_type表

GoodsType.java

public class GoodsTypeimplements java.io.Serializable {

     // Fields

     private Integer typeId;

     private String typeName;

     private Integer typeLv;

     private String typePath;

GoodsType.hbm.xml文件

17.2.2 生成有单向多对一映射关系的Goods表

Goods.java类

public class Goodsimplements java.io.Serializable {

     // Fields

     private Integer goodsId;

     private GoodsTypegoodsType;//这个就是Goods的关联关系对象

     private String goodsName;

     private Float goodsPrice;

     private Integer goodsNum;

     private String goodsImg;

     private Timestamp goodsDate;

private GoodsType goodsType;//这个就是Goods的关联关系对象

     在关系型数据库中两张表之间有关系,用外键关联。

     我们在商品表中保存一个类型的主键字段做为外键,保证两张表之间的关系。

     商品表中的外键字段存在的意义?能找到goods_type表中的一条记录。

     我们java程序是一个面向对象的语言,我们可以商品类中直接创建商品类型对象。

 

Goods.hbm.xml文件

     在这个文件中说明Goods中是如何 从一个goods_type字段变成 了一个GoodsType的对象的。

<class name="com.no8.Goods" table="goods">

<many-to-onename="goodsType" class="com.no8.domain.GoodsType"fetch="select">

     <columnname="goods_type" />

</many-to-one>

</class>

 

17.3 可以级联操作Goods类的关联关系对象goodsType

         GoodsDAO goodsDAO = new GoodsDAO();

         Goods goods = goodsDAO.findById(1);

        

         System.out.println(goods.getGoodsName());

         System.out.println(goods.getGoodsImg());

         System.out.println(goods.getGoodsType().getTypeName());

        

         HibernateSessionFactory.closeSession();

 

17.4 <many-to-one fetch="select|join" 抓取策略

     加载Goods时级联加载goodsType,怎么加载goodsType

     fetch="select"表示使用一条单独的Select语句加载goodsType.

     fetch="join"表示使用连接查询的方法加载goodsType

 

17.5 <many-to-one lazy="proxy|false" 延迟加载,关联级延迟加载

     以延迟的方式加载Goods的级联关系对象goodsType

     但是当goodsType已经加载完成之后 ,后面就直接引用之前加载完成了GoodsType对象。

     一个数据库的记录只有一个持久化状态的对象。

17.6 基于MTO的CRUD

17.6.1 保存一个新商品

     基于MTO,保存一个新商品,有关联关系对象GoodsType。

     1保存一个新商品,属于现在有一个商品类型

         //1 保存一个新商品,属于现在有一个商品类型(3     服装服饰)

         Goods goods = new Goods();

         goods.setGoodsDate(DateUtil.getTimeStamp());

         goods.setGoodsImg("wsc.jpg");

         goods.setGoodsName("包(粉红版)");

         goods.setGoodsPrice(100F);

          goods.setGoodsNum(1);

         //商品的级联关系对象商品类型,如果是数据库中存在的,应该从数据库中加载

         GoodsTypeDAO goodsTypeDAO = new GoodsTypeDAO();

         GoodsType goodsType = goodsTypeDAO.findById(3);

         goods.setGoodsType(goodsType);

        

         GoodsDAO goodsDAO = new GoodsDAO();

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         goodsDAO.save(goods);

         tran.commit();

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

 

     2保存一个新商品,属于现在没有一个商品类型

     使用程序的方式维护新的商品与新的商品类型之间的关系

         //2 保存一个新商品,属于现在没有一个商品类型(箱包饰品)

         Goods goods = new Goods();

         goods.setGoodsDate(DateUtil.getTimeStamp());

         goods.setGoodsImg("wsc.jpg");

         goods.setGoodsName("包(粉红版)");

         goods.setGoodsPrice(100F);

         goods.setGoodsNum(1);

         //商品的级联关系对象商品类型,如果是数据库中不存在的,新保存类型

         GoodsType goodsType = new GoodsType();

         goodsType.setTypeName("箱包饰品");

         goods.setGoodsType(goodsType);//关联商品与类型之间的关系

        

         GoodsTypeDAO goodsTypeDAO = new GoodsTypeDAO();

         GoodsDAO goodsDAO = new GoodsDAO();

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         goodsTypeDAO.save(goodsType);

         goodsDAO.save(goods);

         tran.commit();

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

     通过Hibernate维护新的商品与新的商品类型之间的关系

<many-to-onename="goodsType" class="com.no8.domain.GoodsType"

              lazy="proxy" fetch="select" cascade="save-update">

         //2 保存一个新商品,属于现在没有一个商品类型(箱包饰品)

         Goods goods = new Goods();

         goods.setGoodsDate(DateUtil.getTimeStamp());

         goods.setGoodsImg("wsc.jpg");

         goods.setGoodsName("包(粉红版)");

         goods.setGoodsPrice(100F);

         goods.setGoodsNum(1);

         //商品的级联关系对象商品类型,如果是数据库中不存在的,新保存类型

         GoodsType goodsType = new GoodsType();

         goodsType.setTypeName("箱包饰品");

         goods.setGoodsType(goodsType);//关联商品与类型之间的关系

        

         GoodsDAO goodsDAO = new GoodsDAO();

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         goodsDAO.save(goods);

         tran.commit();

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

17.6.2 修改一个商品信息

     修改一个商品的基本属性(goodsName,goodsPrice)与关联关系有没有影响。

     修改一个商品的所属类型时才会有关联关系对象有关。

     将一个商品(id=83)从A类型(24箱包)修改为B类型(3服饰)

     public staticvoid main(String[] args) {

         //将一个商品(id=86)从A类型(24箱包)修改为B类型(3服饰)

         GoodsDAO goodsDAO = new GoodsDAO();

         GoodsTypeDAO goodsTypeDAO = new GoodsTypeDAO();

        

         Goods goods = goodsDAO.findById(86);

//       GoodsType old = goods.getGoodsType();

//       GoodsType old1 = goodsTypeDAO.findById(24);

         GoodsType goodsType = goodsTypeDAO.findById(3);

         HibernateSessionFactory.getSession().getTransaction().begin();

         goods.setGoodsType(goodsType);

         HibernateSessionFactory.getSession().getTransaction().commit();

        

         HibernateSessionFactory.closeSession();

     }

17.6.3 查询商品,按关联关系对象做为查询条件

     1查询价格在100以上的数码产品

         String hql = "from Goods where goodsPrice >= :goodsPrice"

                   + " and goodsType.typeName = :typeName";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         query.setFloat("goodsPrice", 100);

         query.setString("typeName","数码产品");

         List<Goods> goodsList = query.list();

        

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName() +":"

                       + goods.getGoodsPrice() +":"

                       + goods.getGoodsType().getTypeName());

         }

         HibernateSessionFactory.closeSession();

 

18练习:后台商品管理模块

18.1 获得记录总数量的方法

     public int getCount(SearchVOsearchVO){

         log.debug("getCount");

         try {

              Map<String,Object> map = new HashMap<String, Object>();

              String hql = "select count(*) from Goods where 1=1 ";

              if(searchVO.getGoodsName()!=null){

                   hql += "and goodsName like :goodsName ";

                   map.put("goodsName","%"+searchVO.getGoodsName()+"%");

              }

              if(searchVO.getMinPrice()!=null){

                   hql += "and goodsPrice >= :min ";

                   map.put("min",searchVO.getMinPrice());

              }

              if(searchVO.getMaxPrice()!=null){

                   hql += "and goodsPrice <= :max ";

                   map.put("max",searchVO.getMaxPrice());

              }

              if(searchVO.getTypeId()!=null&& searchVO.getTypeId() != -1){

                   hql +="and goodsType.typeId = :typeId ";

                   map.put("typeId",searchVO.getTypeId());

              }

              Query query = getSession().createQuery(hql);

              //参数设置,为参数赋值。

              query.setProperties(map);

              return (Integer) query.uniqueResult();

         } catch (RuntimeException re) {

              log.error("get failed",re);

              throw re;

         }

     }

18.2 获得当前页的集合

     public List<Goods> search(intpage, int recordOfPage, SearchVO searchVO){

         log.debug("search");

         try {

              Map<String,Object> map = new HashMap<String, Object>();

              String hql = "from Goods where 1=1 ";

              if(searchVO.getGoodsName()!=null){

                   hql += "and goodsName like :goodsName ";

                   map.put("goodsName","%"+searchVO.getGoodsName()+"%");

              }

              if(searchVO.getMinPrice()!=null){

                   hql += "and goodsPrice >= :min ";

                   map.put("min",searchVO.getMinPrice());

              }

              if(searchVO.getMaxPrice()!=null){

                   hql += "and goodsPrice <= :max ";

                   map.put("max",searchVO.getMaxPrice());

              }

              if(searchVO.getTypeId()!=null&& searchVO.getTypeId() != -1){

                   hql +="and goodsType.typeId = :typeId ";

                   map.put("typeId",searchVO.getTypeId());

              }

              Query query = getSession().createQuery(hql);

              //参数设置,为参数赋值。

              query.setProperties(map);

              //设置分页的两个参数

              query.setMaxResults(recordOfPage);//每页的记录数量

              query.setFirstResult((page-1)*recordOfPage);//当前页的启始索引

              return query.list();

         } catch (RuntimeException re) {

              log.error("get failed",re);

              throw re;

         }

     }

18.3 按商品名称查询商品对象

     public Goods findByGoodsName(String goodsName) {

         log.debug("finding Goods instance with property: goodsName, value: "

                   + goodsName);

         try {

              String queryString = "from Goods where goodsName= :goodsName";

              Query queryObject = getSession().createQuery(queryString);

              queryObject.setString("goodsName",goodsName);

              return (Goods) queryObject.uniqueResult();

         } catch (RuntimeException re) {

              log.error("find by property name failed",re);

              throw re;

         }

     }

18.4 Service类中一定要将所有关闭全部删除。编写OpenSessionInViewFilter

18.5 Serivce类中要将事务修改为Hibernate的事务处理

     public boolean save(Goodsgoods) {

         GoodsDAO goodsDAO = new GoodsDAO();

         Transaction tran = HibernateSessionFactory.getSession()

                   .getTransaction();

         try {

              tran.begin();

              goodsDAO.save(goods);

              tran.commit();

              return true;

         } catch (Exception e) {

              e.printStackTrace();

              tran.rollback();

              return false;

         }

     }

 

19 双向一对多映射(核心)

     双向一对多映射就是要同时维护商品到类型的多对一,和类型到商品的一对多。

     在数据库中商品与类型之前是多对一的关系。类型与商品是一对多关系。

     同时映射一对多 和 多对一。

19.1 数据库模型

其中:goods.goods_type是外键字段。

19.2 生成实体类与ORM文件

19.2.1 反向生成时的设置选项

19.2.2 Goods类和GoodsType类

商品类,在这个类中应该有“多对一”的关联关系映射->商品类型的对象。

商品类型类,在这个类中应该有“一对多”的关联关系映射->商品的集合

Goods.hbm.xml文件

     在这个文件里应该有一个“many-to-one”去描述关联关系

GoodsType.hbm.xml文件

     在这个文件里应该有一个“one-to-many”去描述关联关系

 

19.3 <set inverse="true|false" 属性

     控制权反转

     inverse="true"  : 表示放弃控制权

     inverse="false":表示不放弃控制权

 

     现在我们是双向映射。同时维护两边的关系。

     两边关系的确定,最终在数据库中只有一个字段。goods表中的goods_type字段

 

     java程序中,表示商品与类型之间关系的有二个关联关系属性

     1Goods类中有一个GoodsType goodsType 的对象属性。

     2GoodsType类中有一个Set<Goods> goodses 的集合属性。

     这二个关联关系属性同时描述了商品与类型之间的同一个关系。

 

     GoodsTypea = new GoodsType(1);

     GoodsTypeb = new GoodsType(2);

     Goodsg = new Goods();

    

     a.getGoodses().add(g);       goods_type = 1

     g.setGoodsType(b);           goods_type = 2

 

     <set name="goodses"inverse="true">   

     在set节点上inverse="true",表示goodses这个集合放弃控制权。

     对这个集合的操作将不在影响数据库中表示关系的字段的值。

 

19.4 基于双向一对多映射的CRUD操作

19.4.1 在goodses的集合上设置inverse="true",保存时与单向多对一操作一致。

19.4.2 查询一个类型,或以同时将类型的商品级联加载。

     public staticvoid main(String[] args) {

         GoodsTypeDAO goodsTypeDAO = new GoodsTypeDAO();

         GoodsType goodsType = goodsTypeDAO.findById(1);

         System.out.println(goodsType.getTypeName());

         Set<Goods> goodsSet = goodsType.getGoodses();

         for (Goods goods : goodsSet) {

              System.out.println(goods.getGoodsName());

         }

         HibernateSessionFactory.closeSession();

     }

19.4.3 在一对多映射时的HQL语句的格式

     hql有一个叫size()的方法。计算大小。

     //查询所有商品数量大于3的类型。

//       String hql = "from GoodsType where size(goodses) > 3";

         String hql = "from GoodsType where goodses.size > 3";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         List<GoodsType> goodsTypeList = query.list();

         for (GoodsType goodsType : goodsTypeList) {

              System.out.println(goodsType.getTypeName());

         }

         HibernateSessionFactory.closeSession();

 

19.5 在一对多映射时cascade的作用

cascade = 级联策略,表示操作当前对象时如何操作级联关系对象。

     1save

     2save-update

     3all

19.5.1 数据库模型,加入一个imgs表。

     一个商品除了在goods表中有一个图片,还可以有很多详情的图片。

19.5.2 反向生成



19.5.3 在保存商品同时保存商品图片

     public staticvoid main(String[] args) {

         GoodsType goodsType = new GoodsTypeDAO().findById(21);

         //新建一个商品

         Goods goods = new Goods();

         goods.setGoodsName("拿铁");

         goods.setGoodsImg("/wsc.jpg");

         goods.setGoodsPrice(4.0F);

         goods.setGoodsNum(10);

         goods.setGoodsType(goodsType);

         //新建二个图片

         GoodsImg img1 = new GoodsImg();

         img1.setImgPath("img1.jpg");

         GoodsImg img2 = new GoodsImg();

         img2.setImgPath("img2.jpg");

        

         //维护商品与图片之间的关系

//       goods.getGoodsImgs().add(img1);

//       goods.getGoodsImgs().add(img2);

         img1.setGoods(goods);

         img2.setGoods(goods);

        

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         new GoodsDAO().save(goods);

         new GoodsImgDAO().save(img1);

         new GoodsImgDAO().save(img2);

         tran.commit();

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

         System.out.println("end");

     }

     public staticvoid main(String[] args) {

         GoodsType goodsType = new GoodsTypeDAO().findById(21);

         //新建一个商品

         Goods goods = new Goods();

         goods.setGoodsName("拿铁");

         goods.setGoodsImg("/wsc.jpg");

         goods.setGoodsPrice(4.0F);

         goods.setGoodsNum(10);

         goods.setGoodsType(goodsType);

         //新建二个图片

         GoodsImg img1 = new GoodsImg();

         img1.setImgPath("img1.jpg");

         GoodsImg img2 = new GoodsImg();

         img2.setImgPath("img2.jpg");

        

         //维护商品与图片之间的关系

         goods.getGoodsImgs().add(img1);

         goods.getGoodsImgs().add(img2);

         img1.setGoods(goods);

         img2.setGoods(goods);

        

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         new GoodsDAO().save(goods);

//       new GoodsImgDAO().save(img1);

//       new GoodsImgDAO().save(img2);

         tran.commit();

         HibernateSessionFactory.closeSession();

        

         System.out.println(goods.getGoodsId());

         System.out.println("end");

     }

 

20 案例20:保存商品同时保存多张图片

20.1 数据库模型

20.2 静态模型

20.3 Servlet控制器-SaveGoodsController.java

         //要保存的商品对象

         Goods goods = new Goods();

         // 批量文件上传

         List<Part> parts = (List<Part>) request.getParts();

         for (Part part : parts) {

              if("goodsImgs".equals(part.getName())){

                   //单一文件上传

                   String fileRealName = FileNameUtil.getRealFileName(part

                            .getHeader("Content-Disposition"));

                   String fileSaveName = FileNameUtil.getUUIDFileName()

                            + FileNameUtil.getFileType(fileRealName);

                   String path = request.getServletContext().getRealPath("/upimgs");

                   part.write(path +"/" + fileSaveName);

                   //一个商品的图片,需要保存到数据库中

                   GoodsImg goodsImg = new GoodsImg();

                   goodsImg.setImgPath(fileSaveName);

                   //商品有图片,维护商品与图片的关系

                   goods.getGoodsImgs().add(goodsImg);

                   //图片属于商品,维护图片与商品的关系

                   goodsImg.setGoods(goods);

              }

         }

20.4 Service业务层-GoodsService.java

     public boolean save(Goodsgoods) {

         GoodsDAO goodsDAO = new GoodsDAO();

         GoodsImgDAO goodsImgDAO = new GoodsImgDAO();

         Transaction tran = HibernateSessionFactory.getSession()

                   .getTransaction();

         try {

              tran.begin();

              goodsDAO.save(goods);

               //当前没有设置Goods到GoodsImg的cascade。所以代码补

              Set<GoodsImg> goodsImgSet = goods.getGoodsImgs();

              for (GoodsImg goodsImg : goodsImgSet) {

                   goodsImgDAO.save(goodsImg);

              }

              tran.commit();

              return true;

         } catch (Exception e) {

              e.printStackTrace();

              tran.rollback();

              return false;

         }

     }

 

21 修改案例20,单独搭建图片上传服务器


@WebListener

public class InitAppListenerimplements ServletContextListener {

     public void contextInitialized(ServletContextEventarg0) {

         // TODO Auto-generated method stub

         ServletContext context = arg0.getServletContext();

         GoodsTypeSerivce goodsTypeSerivce =new GoodsTypeSerivce();

         List<GoodsType> goodsTypeList = goodsTypeSerivce.findAll();

          context.setAttribute("typeList",goodsTypeList);

        

         String path = context.getRealPath("/");

         String imgPath = path.replace("web1012", "uploadimg")+"upimgs";

         System.out.println(imgPath);

         context.setAttribute("imgPath",imgPath);

     }

     public void contextDestroyed(ServletContextEventarg0) {

     }

}

         // 要保存的商品对象

         Goods goods = new Goods();

         String path = request.getServletContext().getRealPath("/upimgs");

         String imgPath = (String) this.getServletContext().getAttribute("imgPath");

         // 批量文件上传

         List<Part> parts = (List<Part>) request.getParts();

         for (Part part : parts) {

              if ("goodsImgs".equals(part.getName())) {

                   // 单一文件上传

                   String fileRealName = FileNameUtil.getRealFileName(part

                            .getHeader("Content-Disposition"));

                   String fileSaveName = FileNameUtil.getUUIDFileName()

                            + FileNameUtil.getFileType(fileRealName);

                   part.write(imgPath +"/" + fileSaveName);

                    //...

              }

         }

 

22 关系型数据库中的多对多映射

22.1 数据库模型中的多对多映射。

     在关系型数据库中多对多的关系,必须依赖于第三张表。第三张表称关系表。

     关系表中二种情况的方式:有没有业务字段

     1有业务字段:商品与订单的多对多关系

         商品与订单的关系表:

         id(主键),商品id,订单id,订购价格,订购数量(其中订购价格和订购数量就是业务字段)

     2没有业务字段:教员与学员的多对多关系

         教员与学员的关系表:业务只要求能表示教员与学员之间的关系

         教员id,学员id

 

23 使用Hibernate映射-有业务字段的多对多

23.1 数据库模型

在关系型数据库,将订单与商品的多对多关系拆分成了二个多对一关系。

23.2 生成实体类和ORM文件

针对关系表中有业务字段的,在Hibernate中就是将多对多映射拆分成了二个双向一对多映射。

Goods.java

Orders.java

OrderDetails.java

23.3 生成订单功能,实现保存订单时同时保存订单明细

23.3.1 显示所有商品信息

23.3.2 显示商品详情信息

23.3.3 购物车

23.3.4 生成订单

public class OrderService {

     private OrdersDAO ordersDAO = new OrdersDAO();

     private OrderDetailsDAO orderDetailsDAO = new OrderDetailsDAO();

     private GoodsDAO goodsDAO = new GoodsDAO();

 

     public boolean save(Ordersorder) {

         Transaction tran = HibernateSessionFactory.getSession()

                   .getTransaction();

         try {

              tran.begin();

              ordersDAO.save(order);

              Set<OrderDetails> detailsSet =order.getOrderDetailses();

              for (OrderDetails orderDetails : detailsSet) {

                   orderDetailsDAO.save(orderDetails);

                   Goods goods = goodsDAO.findById(orderDetails.getGoods()

                            .getGoodsId());

                   goods.setGoodsNum(goods.getGoodsNum()

                            - orderDetails.getDetailNum());

              }

              tran.commit();

              return true;

         } catch (Exception e) {

              e.printStackTrace();

              tran.rollback();

              return false;

         }

     }

}

     protected void doGet(HttpServletRequest request,

              HttpServletResponse response)throws ServletException, IOException {

         // 1 接收用户请求信息

         String orderName = request.getParameter("orderName");

         String orderPhone = request.getParameter("orderPhone");

         String orderAddress = request.getParameter("orderAddress");

 

         // 2 调用业务逻辑

         // 获得当前登录用户

         Users user = new UserService().findById(1);

 

         Orders order = new Orders();

         order.setOrderId(FileNameUtil.getUUIDFileName());

         order.setOrderName(orderName);

         order.setOrderPhone(orderPhone);

         order.setOrderAddress(orderAddress);

         order.setUsers(user);

 

         // 获得购物车中的商品

         HttpSession session = request.getSession();

         Map<Integer, ItemVO> shopcar = (Map<Integer, ItemVO>)session

                   .getAttribute("shopcar");

         Set<Entry<Integer, ItemVO>> entrySet =shopcar.entrySet();

         for (Entry<Integer, ItemVO> entry : entrySet) {

              OrderDetails details = new OrderDetails();

              details.setDetailNum(entry.getValue().getNum());

              details.setDetailPrice(entry.getValue().getGoods().getGoodsPrice());

              details.setOrders(order);//明细属于哪个订单

              details.setGoods(entry.getValue().getGoods());//明细属于哪个商品

              order.getOrderDetailses().add(details);//订单知道有明细

         }

 

         OrderService service = new OrderService();

         if (service.save(order)) {

              // 清空购物车

              // 显示订单详情页面

              response.sendRedirect(request.getContextPath()

                       + "/order/findbyid.do?orderId=" +order.getOrderId());

         } else {

              response.sendRedirect(request.getContextPath()+"/car.jsp");

         }

 

     }

23.3.5 显示订单详情

 

24 使用Hibernate映射-没有业务字段的多对多映射

24.1 数据库模型

24.2 反向生成实体类与ORM文件

Teacher.java

public class Teacherimplements java.io.Serializable {

     // Fields

     private Integer teaId;

     private String teaName;

     private Set students = new HashSet(0);

Student.java

public class Studentimplements java.io.Serializable {

     // Fields

     private Integer stuId;

     private String stuName;

     private Set teachers = new HashSet(0);

 

当hibernate映射 多对多(many-to-many) , 只用二个实体类就够了。

但是在映射过程中,必须有一方负责维护二者之间的关系。

二者之间的关系是:数据库中的关系表。

现在在当前Student和Teacher中,哪个类有对关系的控制能力?Teacher类可以控制关系。

Teacher类的哪个属性控制?Teacher类中的Set students(学员集合)属性。

24.3 映射关系的维护

案例1:增加一个新的学员(王瑞),做为编号1,孙老师的学员。

     public staticvoid main(String[] args) {

         //案例1:增加一个新的学员(王瑞),做为编号1,孙老师的学员。

         Student s = new Student();

         s.setStuName("王琳琳");

         Teacher t = new TeacherDAO().findById(1);

         //关系

         t.getStudents().add(s);

         s.getTeachers().add(t);

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         new StudentDAO().save(s);

         tran.commit();

        

         HibernateSessionFactory.closeSession();

         System.out.println("end!");

     }

 

案例2:将一个学员(编写6, 王梦),从孙老师(1)移到张老师(2)

     public staticvoid main(String[] args) {

         //案例2:将一个学员(编写6,王梦),从孙老师(1)移到张老师(2

         Student s = new StudentDAO().findById(6);

         Teacher t1 = new TeacherDAO().findById(1);

         Teacher t2 = new TeacherDAO().findById(2);

        

         HibernateSessionFactory.getSession().getTransaction().begin();

         s.getTeachers().remove(t2);

         t2.getStudents().remove(s);

         s.getTeachers().add(t1);

         t1.getStudents().add(s);

        

         HibernateSessionFactory.getSession().getTransaction().commit();

        

         HibernateSessionFactory.closeSession();

 

         System.out.println("end!");

     }

 

25 自连接映射

     自连接:就是一张表中的字段做为外键,引用自己表中的主键。

     商品类型表中使用自连接。

25.1 数据库模型




25.2 生成实体类与ORM文件

25.3 保存一个第一级的商品类型

     public staticvoid main(String[] args) {

         //保存第一级类型

         GoodsType goodsType = new GoodsType();

         goodsType.setTypeName("书籍资料");

         goodsType.setTypeLv(1);

        

         Transaction tran = HibernateSessionFactory.getSession().getTransaction();

         tran.begin();

         new GoodsTypeDAO().save(goodsType);//保存操作,对象状态修改为持久态,主键赋值。

         goodsType.setTypePath("|"+goodsType.getTypeId()+"|");//修改类型的path属性。

         tran.commit();

        

         HibernateSessionFactory.closeSession();

         System.out.println("end");

     }

25.4 在25.书籍资料下加入一个新的子类型

     public staticvoid main(String[] args) {

         // 25.书籍资料下加入一个新的子类型

         GoodsType pgoodstype = new GoodsTypeDAO().findById(25);

 

         GoodsType goodsType = new GoodsType();

         goodsType.setGoodsType(pgoodstype);//设置当前类型的父类型。

         // pgoodstype.getGoodsTypes().add(goodsType);

         goodsType.setTypeName("英语书籍");

         goodsType.setTypeLv(pgoodstype.getTypeLv() + 1);

 

         Transaction tran = HibernateSessionFactory.getSession() .getTransaction();

         tran.begin();

         // 保存操作,对象状态修改为持久态,主键赋值。

         new GoodsTypeDAO().save(goodsType);

         // 修改类型的path属性。

         goodsType.setTypePath(pgoodstype.getTypePath() +"|"

                   + goodsType.getTypeId() +"|");

         tran.commit();

 

         HibernateSessionFactory.closeSession();

 

         System.out.println("end");

     }

25.5 查询一个类型(4 照相机),要显示这个类型的父类型和所有子类型

     public staticvoid main(String[] args) {

         //25.5 查询一个类型(照相机),要显示这个类型的父类型和所有子类型

         GoodsType goodstype = new GoodsTypeDAO().findById(4);

 

         System.out.println("显示当前类型节点的信息");

         System.out.println(goodstype.getTypeName());

         System.out.println(goodstype.getTypeLv());

         System.out.println("显示父类型节点的信息");

         System.out.println(goodstype.getGoodsType().getTypeName());

         System.out.println(goodstype.getGoodsType().getTypeLv());

         System.out.println("显示所有子类型节点的信息");

         Set<GoodsType> goodsTypeSet = goodstype.getGoodsTypes();

         for (GoodsType type : goodsTypeSet) {

              System.out.println(type.getTypeName());

              System.out.println(type.getTypeLv());

              System.out.println("----------");

         }

        

         HibernateSessionFactory.closeSession();

         System.out.println("end");

     }

25.6查询所有属于商品类型(3   服装服饰)的商品信息

     public staticvoid main(String[] args) {

         //25.6 查询所有属于商品类型(服装服饰)的商品信息

         int typeId = 3;//查询商品的类型编号

          // GoodsType goodsType = new GoodsTypeDAO().findById(typeId);

         // System.out.println(goodsType.getGoodses().size());

         String hql = "from Goods g where g.goodsType.typePath like :typeId";

         Query query = HibernateSessionFactory.getSession().createQuery(hql);

         query.setString("typeId","%|"+typeId+"|%");

         System.out.println(query.list());

         System.out.println(query.list().size());

         HibernateSessionFactory.closeSession();

         System.out.println("end");

     }

 

26 QBC-按条件查询

Hiernate查询:

     1成生DAO。

     2Session对象的load方法,和get方法。

     3 HQL(使用比较多,与SQL语句很像)

     4 QBCQBE(面向对象的查询方式,推荐使用)

     5 SQL-原生的SQL语句

Query、Criteria、SqlQuery这三个接口

Criteria本身只是个查询容器,具体的查询条件需要通过Cretiria.add方法添加Criterion到Criteria实例中。

Restrictions的一系列静态方法可以创建Criterion对象,

Criterion具体描述查询条件,针对SQL语法,Criterion提供了对应的查询限定机制。

26.1 获得Criteria接口

与Query接口的方式一致,通过Session的方法获得Criteria接口的实例。

     public void qbc01(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

     }

26.2 基础查询-查询所有

     //查询所有商品

     public void qbc02(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

26.3 条件查询

Criteria本身只是个查询容器,具体的查询条件需要通过Cretiria.add方法添加Criterion到Criteria实例中。

Criterion具体描述查询条件,针对SQL语法,Criterion提供了对应的查询限定机制

Restrictions的一系列静态方法可以创建Criterion对象

26.3.1 Restrictions的一系列静态方法如下:

26.3.2 基础条件查询

查询商品价格大于200的商品

 

     @Test

     //查询商品价格大于200的商品

     public void qbc03(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion = Restrictions.gt("goodsPrice", 2000f);

         criteria.add(criterion);

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

26.3.3 between...and...

     public void qbc03(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion = Restrictions.between("goodsPrice", 2000f, 3000f);

         criteria.add(criterion);

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

26.3.4 like 模糊查询

查询所有类型属于3、服装服饰的商品类型

     @Test

     //查询所有类型属于3、服装服饰的商品类型

     public void qbc04(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(GoodsType.class);

         //创建的一个查询条件对象

         Criterion criterion = Restrictions.like("typePath","|3|", MatchMode.ANYWHERE);

         criteria.add(criterion);

         List<GoodsType> goodsTypeList = criteria.list();

         for (GoodsType goodsType : goodsTypeList) {

              System.out.println(goodsType.getTypeId());

              System.out.println(goodsType.getTypeName());

         }

         HibernateSessionFactory.closeSession();

     }

26.3.5 in (...)

查询所有抽奖的商品(1,5,8,9)

     @Test

     //查询所有抽奖的商品(1589

     public void qbc05(){

         List<Integer> goodsIds = new ArrayList<Integer>();

         goodsIds.add(1);

         goodsIds.add(5);

         goodsIds.add(8);

         goodsIds.add(9);

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion = Restrictions.in("goodsId",goodsIds);

         criteria.add(criterion);

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

 

26.4 and 与

     在Hibernate中有三种方式可以实现“与”条件

26.4.1 使用多个criteria.add方法,每个条件就是“与”关系

     查询价格大2000并数量大100

     @Test

     //查询价格大2000并数量大100

     public void qbc06(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion1 = Restrictions.gt("goodsPrice", 2000f);

         Criterion criterion2 = Restrictions.lt("goodsNum", 100);

         //将条件以的方式连接起来

         criteria.add(criterion1).add(criterion2);

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

26.4.2 使用Restrictions.add方法连接多个“与”运算的条件

     @Test

     //查询价格大2000并数量小100

     public void qbc07(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion1 = Restrictions.gt("goodsPrice", 2000f);

         Criterion criterion2 = Restrictions.lt("goodsNum", 100);

         //创建了一个运算的查询条件

         Criterion criterion3 = Restrictions.and(criterion1,criterion2);

         criteria.add(criterion3);

         //执行查询

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

26.4.3 使用Restrictions.conjunction()获得一个“与”运算条件对象(个人推荐)

     Conjunctionconjunction = Restrictions.conjunction()

     conjunction.add(Criterion);

     conjunction.add(Criterion);

     conjunction.add(Criterion);

     @Test

     //查询价格大2000并数量小100

     public void qbc07(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion1 = Restrictions.gt("goodsPrice", 2000f);

         Criterion criterion2 = Restrictions.lt("goodsNum", 100);

         //创建了一个运算的查询条件

         Conjunction conjunction = Restrictions.conjunction();

         conjunction.add(criterion1);

         conjunction.add(criterion2);

         //运算的查询条件加到查询对象中

         criteria.add(conjunction);

         //执行查询

         List<Goods> goodsList = criteria.list();

         for (Goods goods : goodsList) {

              System.out.println(goods.getGoodsName());

              System.out.println(goods.getGoodsPrice());

              System.out.println(goods.getGoodsType().getTypeName());

              System.out.println("---------");

         }

         HibernateSessionFactory.closeSession();

     }

 

 

 

26.5 or 或

     在Hibernate的QBC中只有二种实现方式:

26.5.1 使用Restrictions.or方法

     @Test

     //查询价格小2000或数量大于100

     public void qbc08(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion1 = Restrictions.lt("goodsPrice", 2000f);

         Criterion criterion2 = Restrictions.gt("goodsNum", 100);

         Criterion criterion3 = Restrictions.or(criterion1,criterion2);

         criteria.add(criterion3);

         //执行查询

         List<Goods> goodsList = criteria.list();

         HibernateSessionFactory.closeSession();

     }

26.5.2 使用Restrictions.disjunction()实现“或”关系的运算

     @Test

     //查询价格大2000或数量小100

     public void qbc09(){

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //创建的一个查询条件对象

         Criterion criterion1 = Restrictions.gt("goodsPrice", 2000f);

         Criterion criterion2 = Restrictions.lt("goodsNum", 100);

         //创建了一个运算的查询条件

         Disjunction disjunction = Restrictions.disjunction();

         disjunction.add(criterion1);

         disjunction.add(criterion2);

         //运算的查询条件加到查询对象中

         criteria.add(disjunction);

         //执行查询

         List<Goods> goodsList = criteria.list();

         HibernateSessionFactory.closeSession();

     }

26.6 关联关系查询

createCriteria创建关联Criteria

createAlias创建关联对象的别名

26.6.1 X对一

查询商品,条件商品类型=“家用电器”并价格大于1000

sql : select * from goods inner joingoods_type on goods.goods_type = goods_type.type_id

         wheregoods_type.type_name = '家用电器' and goods.goods_price > 1000

hql : from Goods g where g.goodsPrice >1000 and g.goodsType.typeName = '家用电器'

QBC: 两种方式:

     1使用createCriteria为关联关系对象创建一个新查询

     public void qbc10() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         criteria.add(Restrictions.gt("goodsPrice", 1000f));

         criteria.createCriteria("goodsType")

              .add(Restrictions.eq("typeName","家用电器"));

         // 执行查询

         List<Goods> goodsList = criteria.list();

         HibernateSessionFactory.closeSession();

     }

     2使用createAlias为关联关系对象创建一个别名(实例名称)

     public void qbc11() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class,"g");

         criteria.createAlias("g.goodsType","t");//就是给关联关系对象启名

         criteria.add(Restrictions.gt("g.goodsPrice", 1000f));

         criteria.add(Restrictions.eq("t.typeName","家用电器"));

         // 执行查询

         List<Goods> goodsList = criteria.list();

         HibernateSessionFactory.closeSession();

     }

26.6.2 X对多

查询商品数量大于3个的商品类型

     //查询商品数量大于3个的商品类型

     public void qbc12() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(GoodsType.class);

         criteria.add(Restrictions.sizeGt("goodses", 3));

         // 执行查询

         List<GoodsType> goodsTypeList = criteria.list();

         HibernateSessionFactory.closeSession();

     }

查询商品价格在3000以上的商品类型

     1使用关联查询

     @Test

     // 查询商品价格在3000以上的商品类型

     public void qbc13() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(GoodsType.class);

         criteria.createCriteria("goodses").add(

                   Restrictions.gt("goodsPrice", 3000f));

         //去重

         criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

         // 执行查询

         List<GoodsType> goodsTypeList = criteria.list();

         for (GoodsType goodsType : goodsTypeList) {

              System.out.println(goodsType.getTypeName());

         }

         HibernateSessionFactory.closeSession();

     }

     2使用别名

     @Test

     // 查询商品价格在3000以上的商品类型

     public void qbc14() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(GoodsType.class);

         criteria.createAlias("goodses","g").add(

                   Restrictions.gt("g.goodsPrice", 3000f));

         //去重

         criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

         // 执行查询

         List<GoodsType> goodsTypeList = criteria.list();

         for (GoodsType goodsType : goodsTypeList) {

              System.out.println(goodsType.getTypeName());

         }

         HibernateSessionFactory.closeSession();

     }

 

26.7 投影查询

     投影查询:只查询表中的某几列

26.7.1 单列的投影查询

     单列的投影查询时,因为查询结果只有一列,如果结果为多行,返回类型就是一个集合。

     但因为是一列,所以集合的泛型就是这个列的类型。

     @Test

     // 单列的投影查询 select goods_name from goods;

     public void qbc15() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //设置投影的列

         criteria.setProjection(Projections.property("goodsName"));

         //查询,只有一列,集合泛型就是这个列的类型

         List<String> goodsNameList = criteria.list();

         for (String goodsName : goodsNameList) {

              System.out.println(goodsName);

         }

         HibernateSessionFactory.closeSession();

     }

26.7.2 多列的投影查询

     多列投影查询因为查询的属性是多个,返回集合的泛型应该是Object[]

     @Test

     // 多列的投影查询 select goods_name,goods_price from goods;

     public void qbc16() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //设置投影的列

         criteria.setProjection(

              Projections.projectionList()

                   .add(Projections.property("goodsName"))

                   .add(Projections.property("goodsPrice"))

         );

         //查询,只有多列,集合泛型就是Object[]

         List<Object[]> goodsList = criteria.list();

         for (Object[] objects : goodsList) {

              for (Object object : objects) {

                   System.out.println(object);

              }

              System.out.println("----------");

         }

         HibernateSessionFactory.closeSession();

     }

     在讲hql语句时,就可以将Object[]换成Map集合,在QBC里面也可以将Object[]换成Map集合

         1在调用add方法时一定要设置别名

              .add(Projections.property("goodsName"),"name")

         2在查询之前 设置 将别名映射成Map

              criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);

     @Test

     // 多列的投影查询 select goods_name,goods_price from goods;

     public void qbc17() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //设置投影的列时,在调用add方法时一定要为列设置别名

         criteria.setProjection(

                   Projections.projectionList()

                   .add(Projections.property("goodsName"),"name")

                   .add(Projections.property("goodsPrice"),"price")

                   );

         //设置一个参数,将多列投影查询映射成Map集合

         criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);

          //查询,集合泛型就是Map<String,Object>

         List<Map<String, Object>> goodsList =criteria.list();

         for (Map<String, Object> map : goodsList) {

              System.out.println(map.get("name"));

              System.out.println(map.get("price"));

              System.out.println("-------------");

          }

         HibernateSessionFactory.closeSession();

     }

26.7.3 投影查询支持SQL运算

     sql:selectgoods_price * goods_num as sumprice from goods;

     @Test

     // sql:select goods_name,goods_price*goods_num as sumprice from goods;

     public void qbc18() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //设置投影的列时,在调用add方法时一定要为列设置别名

         criteria.setProjection(

                   Projections.projectionList()

                   .add(Projections.property("goodsName"),"name")

                   .add(Projections.sqlProjection(

                            "goods_price*goods_num as sumprice",

                            new String[]{"sumprice"},

                            new Type[]{new DoubleType()}))

                   );

         //设置一个参数,将多列投影查询映射成Map集合

         criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);

         //查询,集合泛型就是Map<String,Object>

          List<Map<String, Object>> goodsList =criteria.list();

         for (Map<String, Object> map : goodsList) {

              System.out.println(map.get("name"));

              System.out.println(map.get("sumprice"));

              System.out.println("-------------");

         }

         HibernateSessionFactory.closeSession();

     }

 

26.8 聚合函数

     count(),sum(),min(),max(),avg()

     sql: select count(*) from goods;

     @Test

     // sql:select count(*) from goods;

     public void qbc19() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         // 设置投影的列时

         criteria.setProjection(Projections.rowCount());

         // 查询,有聚合函数不分组,一定只有一条记录

         Long count = (Long) criteria.uniqueResult();

         System.out.println(count);

         HibernateSessionFactory.closeSession();

     }

 

     @Test

     // sql:select count(goods_img) from goods;

     public void qbc20() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         // 设置投影的列时

         criteria.setProjection(Projections.count("goodsImg"));

         // 查询,有聚合函数不分组,一定只有一条记录

         Long count = (Long) criteria.uniqueResult();

         System.out.println(count);

         HibernateSessionFactory.closeSession();

     }

 

     @Test

     // sql:select max(goods_price) as maxPrice,min(goods_price) from goods;

     public void qbc21() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(Goods.class);

         //设置投影的列时

         criteria.setProjection(

              Projections.projectionList()

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

              .add(Projections.max("goodsPrice"),"maxPrice")

              .add(Projections.min("goodsPrice"),"minPrice")

         );

         criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);

         //查询,有聚合函数不分组,一定只有一条记录

         Map<String, Object> map =  (Map<String, Object>)criteria.uniqueResult();

         System.out.println(map.get("count"));

         System.out.println(map.get("maxPrice"));

         System.out.println(map.get("minPrice"));

         HibernateSessionFactory.closeSession();

     }

26.9 分组查询

     统计每个商品的销售情况,包含销售总数,销售总额。

     销售情况在哪张表?订单明细表

     每个商品:按商品分组

     销售总数:sum(销售数量)

     销售总额:sum(数量*单价)

     SQL:select sum(detail_num),sum(detail_num*detail_price) fromorderdetails group by detail_goods;

     @Test

     //sql:

     // select detail_goods,sum(detail_num),sum(detail_num*detail_price)

     // from order_details group by detail_goods

     public void qbc22() {

         Session session = HibernateSessionFactory.getSession();

         Criteria criteria = session.createCriteria(OrderDetails.class);

         // 设置投影的列时

         criteria.setProjection(Projections.projectionList()

                   .add(Projections.property("goods"),"goods")

                   .add(Projections.sum("detailNum"),"sumNum")

                   .add(Projections.sqlProjection("sum(detail_num*detail_price) as sumPrice",

                            new String[]{"sumPrice"},

                            new Type[]{new DoubleType()}))

                   .add(Projections.groupProperty("goods"))

                   );

         criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);

         // 查询,有聚合函数不分组,一定只有一条记录

         List<Map<String, Object>> detailGroupList =criteria.list();

         for (Map<String, Object> map : detailGroupList) {

              Goods goods = (Goods) map.get("goods");

              Long sum = (Long) map.get("sumNum");

              Double sumPrice = (Double) map.get("sumPrice");

              System.out.println(goods.getGoodsName());

              System.out.println(sum);

              System.out.println(sumPrice);

              System.out.println("----------");

         }

         HibernateSessionFactory.closeSession();

     }

 

 

26.10 去重复行

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

查询所有被购买过的商品

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击