hibernate Api

hibernate

hibernate架构

重要对象

  • Transaction Object 瞬时对象(与数据库无关对象)

  • persistent Object 持久对象 (与数据库有关系的对象,保存到数据的对象)

  • session 数据库会话对象

  • sessionFactory 会话工程,进程级别的对象

  • Transaction 事物

  • TransactionFactory 事物工厂

  • ConnectionProvider 数据源例如c3p0,dbcp(链接)

  • JND:提供资源目录

  • JDBC:操作数据库的api

  • JTA:跨数据库的事物

hibernate官网资源部解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OUjymQPd-1604992447268)(/Users/luohengyi/Library/Application Support/typora-user-images/image-20200525095909381.png)]

hibernate环境搭建

倒入jar包

antlr-2.7.7.jar
c3p0-0.9.2.1.jar
dom4j-1.6.1.jar
ehcache-core-2.4.3.jar
hibernate-c3p0-4.3.11.Final.jar
hibernate-commons-annotations-4.0.5.Final.jar
hibernate-core-4.3.11.Final.jar
hibernate-ehcache-4.3.11.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
jandex-1.1.0.Final.jar
javassist-3.18.1-GA.jar
jboss-logging-3.1.3.GA.jar
jboss-logging-annotations-1.2.0.Beta1.jar
jboss-transaction-api_1.2_spec-1.0.0.Final.jar
mchange-commons-java-0.2.3.4.jar
mysql-connector-java-5.0.8.jar
slf4j-api-1.6.1.jar

配置factory
<?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">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>

    </session-factory>

</hibernate-configuration>
配置hibernate
<?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://localhost:3306/hibTest</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123123</property>

        <!-- JDBC connection pool (use the built-in) 设置数据库的初始化连接池数 -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect 方言-->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

        <!-- Enable Hibernate's automatic session context management -->
<!--        <property name="current_session_context_class">thread</property>-->

        <!-- Disable the second-level cache  -->
<!--        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>-->

        <!-- Echo all executed SQL to stdout -->
<!--        <property name="show_sql">true</property>-->

        <!-- Drop and re-create the database schema on startup -->
<!--        <property name="hbm2ddl.auto">update</property>-->

        <mapping resource="com/yguard/bean/user.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

通过配置文件生成数据库

// 创建配置对象
Configuration configuration = new Configuration();
//指定 hibernate-config.xml 位置
configuration.configure("hibernate-config.xml");
//创建表的对象
SchemaExport schemaExport = new SchemaExport(configuration);

schemaExport.create(true,true);

SessionFactory与Session的创建

Configuration configuration = new Configuration();
//指定 hibernate-config.xml 位置 默认根目录
configuration.configure("hibernate-config.xml");

//注册配置信息
ServiceRegistry registry = new StandardServiceRegistryBuilder()
        .applySettings(configuration.getProperties()).build();

//创建 SessionFactory
SessionFactory factory = configuration.buildSessionFactory(registry);
//创建 session
Session session = factory.openSession();
事务
//创建 session
Session session = factory.openSession();
//开启事务
Transaction transaction=session.beginTransaction();
User user = new User("luohengyi",1,new Date());
session.save(user);

//提交事务
transaction.commit();
//销毁session
session.close();

基本配置

hibernate.cfg.xml剖析

hibernate.cfg.xml是默认文件名称,可以随便起名

  • 数据链接配置
  • 可选配置
  • 资源注册
  • 二级缓存
  • 查询缓存
  • 注册 映射文件
数据链接配置
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibTest</property>
<property name="connection.username">root</property>
<property name="connection.password">123123</property>
可选配置

使用默认的数据库连接池,connection.pool_size 是链接池数量

<!-- JDBC connection pool (use the built-in) 设置数据库的初始化连接池数 -->
<property name="connection.pool_size">1</property>

数据库方言 不同的数据库的sql有差别,hibernate可以根据配置生成不同sql语句

<!-- SQL dialect 方言-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

是否输出sql 控制台输出sql

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>

第三方数据库连接池配置 (配置后就开始使用c3p0)

<!--        最小连接数-->
<property name="c3p0.min_size">10</property>
<!--        最大连接数-->
<property name="c3p0.max_size">100</property>
<!--        连接超时时间(毫秒)-->
<property name="c3p0.timeout">3000</property>

建表策略

  • None:不做任何事
  • create:每次执行hibernate的操作都删表建表
  • create-drop:每次执行hibernate的操作都删表建表,SessionFactory关闭就删表
  • validate:每次执行hibernate的操作就验证数据库的表和mapping的关系是否正确
  • update:实体名称变化,原来实体生成的表不删除,而是生成新的实体的表。类中添加新的字段,则生成新的数据表列,类中删除一个字段,则该字段在数据库中生成的列不会删除,对应的数据库属性也不会受到影响;
<!--        create自动建表(删除原来的表)create-drop SessionFactory 销毁时删除表( factory.close)  validate对比映射 更新 配置中有的字段到数据库中 -->
        <property name="hibernate.hbm2ddl.auto">validate</property>
注册 映射文件
<mapping resource="com/yguard/bean/user.hbm.xml"/>

模型类的规范

使用包装类

映射文件配置

每一个model都有一个相当于的映射文件,命名规范:模型类.hbm.xml

<!--  package:指定映射文件的实体类model所在的包-->
<hibernate-mapping package="com.yguard.bean">
<!--
    class:映射类
        name:要映射的model的全路径
        table:model映射到数据库的表名
-->
    <class name="User" table="t_user">

        <id name="userId" column="user_id" >
            <!--   generator:主键生产策略
                        assigned 手动指定id
                        increment 查询最大的id+1,存在并发安全问题
                        identity 使用mysql的自增值类型,model类型必须是id
                        sequence oracle 数据的自增方式
                        native 智能的自增方式,识别数据库的类型来使用不用的策略
                        uuid 使用uuid的方式,要是id是字符类型
 												foreign 外键方式
            -->
            <generator class="uuid"></generator>
        </id>
        <!--
            property:属性类型的映射
                    name:属性名称
                    column:字段名
                    type:类型名称
                    length:字段长度
                    not-null:是否非空
                    unique-key:是否唯一
        -->
        <property name="uname" column="name" unique-key=""/>
        <property name="gender" column="gender"/>
        <property name="birthday" column="birthday"/>
    </class>
</hibernate-mapping>

环境初始化

  • Configuration:创建hibernate对象读取配置信息(hibernate.cfg.xml)
  • ServiceRegistry:注册配置对象
  • SessionFactory:线程安全,负责创建session
  • session:是一次和数据库的会话,不一定只是1次链接,操作对象,影响数据库
  • Transaction:事务对象,控制sesson对数据库的事务影响

Hibernate中实体类3种状态

  • 瞬时对象

    在数据库没有相应记录,没有被session管理,可以被jvm回收

  • 持久化对象

    在数据库中有对应记录,被session管理

  • 托管对象

    在数据库中有对应记录,没有被session管理,可以被jvm回收

image-20200529104946273 image-20200602225137786

Session 的 flush 方法解析

数据库隔离级别
  • 脏读:单个事务之间可以并发读取数据,允许读取到未提交的脏数据
  • 不可重复读:一个事务先后读取同一条记录,而事务在两次读取之间该数据被其它事务所修改,则两次读取的数据不同,当事务启动时,就不允许进行“修改操作(Update)”了。
  • 幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。

一个事务未提交的业务结果是否对于其它事务可见 有4个 级别

脏读不可重复读幻读
Read uncommitted(读未提交)YYY
Read committedNYY
Repeatable readNNY
SerializableNNN
session的flush

主键为UUID方式:

  • save方法:

    ​ 把 user 对象存储在session的临时存储区,在session持久区把dirty变为true

  • evict方法:

    ​ 把user逐出session的管理,user就是脱管状态,此时调用flush方法不会执行sql

  • flush方法:

    发出sql语句清理临时存储区,把dirty变成false(是否是脏数据)

  • commit:

    如果调用了evict方法,将不会提交数据

主键为自增加方式:

  • save方法:

    因为使用native方式生产主键,所以save的时候发出sql来产生主键,持久区有数据dirty变为true

  • evict方法:

    把user逐出session的管理,session中没有数据在调用flush方法没有意义

  • flush方法:

    把dirty变成false

  • commit:

    如果调用了evict方法,依然会提交数据应为sql语句已经发出了

session.flush完成大量数据入库

在调用 commit 方法时会自动调用flush方法

Transaction transaction=session.beginTransaction();
for (int i = 0; i < 11; i++) {
    User user = new User("luohengyi",1,new Date());
    session.save(user);
    if (i%2==0){
        session.flush();
    }
}
transaction.commit();

关联映射(学习完后再次测试)

多对一关联
<class name="Emp" table="t_emp">
    <id name="empNum" column="emp_num">
        <generator class="native"></generator>
    </id>
    <property name="ename" />
    <property name="birthday"/>
    <property name="gender" />
    <property name="address" />
    <!--  指定 多(emp)对一(tem) 的关系  -->
    <!--  name: 用来装 一端(tem) 的数据类属性名-->
    <!--  column:建表后一端(tem) 中的外键,emp类 中用来存对应关系的 属性名  -->
    <!--  cascade:delete  级联删除,多对一中才不要使用
                      save-update    级联保存,更新,使用级连更新 不需要单独保存一的一段了
                      all     delete+save-update
                      none     不使用
          -->
    <many-to-one name="team" column="t_id" cascade="save-update"/>
</class>
一对一单向关联(副表)
    <class name="IDCart" table="t_id_cart">

        <id name="cartId" column="emp_no">
            <!--   generator:主键生产策略
                        foreign 外键方式
            -->
            <!--      在保存IDCart 的时候自动保存 emp 因为使用同一个id主键     -->
            <generator class="foreign">
                <!-- foreign  指定idCart这一端的Emp属性名-->
                <param name="property">emp</param>
            </generator>
        </id>
        <property name="carNo" column="car_no" unique-key=""/>
        <!--
        一对一关联
        name: Emp属性名
        constrained: 关联关系防止删除引用
        -->
        <one-to-one name="emp" constrained="true"/>

    </class>
</hibernate-mapping>
一对一双向关联(主表)
<class name="Emp" table="t_emp">

    <id name="empNum" column="emp_num">
        <generator class="native"></generator>
    </id>

    <property name="ename"/>
    <property name="birthday"/>
    <property name="gender"/>
    <property name="address"/>
 
    <one-to-one name="cart"  ></one-to-one>
</class>

双向关联必须手动 set 两个表的应用,并且手动保存2个表

Emp emp1 = new Emp();
emp1.setEname("罗恒一11");
emp1.setAddress("addr");
emp1.setGender(1);
emp1.setBirthday(new Date());

IDCart idCart = new IDCart();
idCart.setCarNo("11cccc");

idCart.setEmp(emp1);
emp1.setCart(idCart);

session.save(emp1);
session.save(idCart);
transaction.commit();

若是想自动保存副表数据 应配置 级联 cascade=“save-update”

<class name="Emp" table="t_emp">
  <id name="empNum" column="emp_num">
      <generator class="native"></generator>
  </id>

  <property name="ename"/>
  <property name="birthday"/>
  <property name="gender"/>
  <property name="address"/>

  <one-to-one name="cart"  cascade="save-update"></one-to-one>
</class>
一对多关联
<class name="Team" table="t_team">

    <id name="tId" column="t_id">
        <generator class="native"></generator>
    </id>

    <property name="tName" column="t_name"/>
    <property name="loc" />
    <!--  
					set 集合类型/可以是其他集合类型
          key column 外键名称
          one-to-many class 类名
					cascade="save-update" 级联 插入team时,自动插入team上的Emp数据
     -->
    <set name="set" cascade="save-update" >
        <key column="t_id"></key>
        <one-to-many class="Emp"></one-to-many>
    </set>

</class>

*缺点

Hibernate: insert into t_team (t_name, loc) values (?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address) values (?, ?, ?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address) values (?, ?, ?, ?)
Hibernate: update t_emp set t_id=? where emp_num=?
Hibernate: update t_emp set t_id=? where emp_num=?

打印的sql中出现了 update 语句,这是对 插入时外键为空的 数据引用问题处理。如果外键为空那么会插入失败

一对多关联双向关联
<class name="Emp" table="t_emp">
        <id name="empNum" column="emp_num">
            <generator class="native"></generator>
        </id>
        <property name="ename"/>
        <property name="birthday"/>
        <property name="gender"/>
        <property name="address"/>
        <!--
         column:一对多中 副表外键名
         -->
        <many-to-one name="team" cascade="save-update" inverse="true"/>
    </class>
<class name="Team" table="t_team">

    <id name="tId" column="t_id">
        <generator class="native"></generator>
    </id>

    <property name="tName" column="t_name"/>
    <property name="loc" />
				 <!--
         	column:一对多中 副表外键名
					inverse="true"  控制反转,此时外键关系不再由Team来维护,需要使 Emp多端来维护
         -->
    <set name="set" cascade="save-update" inverse="true">
        <key column="t_id"></key>
        <one-to-many class="Emp"></one-to-many>
    </set>

</class>

开启inverse="true"控制反转由保存 一 端来保存数据,由多端来维护外键关系

Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Team team = new Team();
team.settName("公牛");
team.setLoc("芝加哥");
Set<Emp> emps = new HashSet<>();

Emp emp = new Emp();
emp.setEname("乔丹");
emp.setGender(1);
emp.setBirthday(new Date());
emp.setAddress("芝加哥");
//多端来维护关系
emp.setTeam(team);
emps.add(emp);


emp = new Emp();
emp.setEname("乔丹1");
emp.setGender(1);
emp.setBirthday(new Date());
emp.setAddress("芝加哥1");
//多端来维护关系
emp.setTeam(team);
emps.add(emp);

team.setSet(emps);
//只需要保存 一 端
session.save(team);
transaction.commit();
多对多关联
<class name="Emp" table="t_emp">

        <id name="empNum" column="emp_num">
            <generator class="native"></generator>
        </id>
 
        <property name="ename"/>
        <property name="birthday"/>
        <property name="gender"/>
        <property name="address"/>
        <!--
            多对多配置
            员工 <- 中间表 -> 角色
            name:员工的角色属性名
            table:中间表的名称
						cascade:保存时只需要保存 员工 表,中间表和角色表自动维护
         -->
        <set name="roles" table="emp_role" cascade="save-update">
            <!--
               key/column: 员工(emp)在中间表中的外键
            -->
            <key column="emp_num"></key>
            <!--
                class:角色的类名
                column:角色在中间表的外键
            -->
            <many-to-many column="role_id" class="Role"></many-to-many>
        </set>

    </class>
多对多双向

双方一致只是在不通的角度来配置

待研究问题
  • 非主键多对多
  • 注解

注解驱动

@Entity

​ 被标注的类指定为实体bean,并且使用默认的orm规则,即class名即数据库表中表名class字段名即表中的字段名

@Table

改变class名与数据库中表名的映射规则

  • name

    属性用于指定数据库的表明

  • UniqueConstraint []

    表示那些字段是 为唯一标识

@Id

属性标识为数据库表中的主键

@GeneratedValue

为主键的生成策略

  • strategy 声明了主键生成器的名称

    GenerationType.TABLE

    使用一个特定的数据库表格来保存主键,该策略一般与另外一个注解一起使用@TableGenerator,@TableGenerator注解指定了生成主键的表

    GenerationType.SEQUENCE

    "序列(sequence)"的机制生成主键,主要用于 Oracle,PostgreSQL,DB2

    GenerationType.IDENTITY

    主键自增长,数据库在插入数据时,会自动给主键赋值,比如MYSQL可以在创建表时声明"auto_increment" 来指定主键自增长

    GenerationType.AUTO

    根据数据库在以上三种主键生成策略中选择其中一种

  • generator

    声明主键生成器的名称–暂时找不到其他资料

@Column

用来标识实体类中属性与数据表中字段的对应关系

  • name

    定义了被标注字段在数据库表中所对应字段的名称;

  • unique

    表示该字段是否为唯一标识,默认为false。如果表中有一个字段需要唯一标识,则既可以使用该标记,也可以使用@Table标记中的@UniqueConstraint。

  • nullable

    表示该字段是否可以为null值,默认为true

  • insertable

    表示在使用“INSERT”脚本插入数据时,是否需要插入该字段的值。

  • updatable

    表示在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值。insertable和updatable属性一般多用于只读的属性,例如主键和外键等。这些字段的值通常是自动生成的

  • columnDefinition(大多数情况,几乎不用)

    表示创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用。(也就是说,如果DB中表已经建好,该属性没有必要使用。)

  • table

    表示当映射多个表时,指定表的表中的字段。默认值为主表的表名。

  • length

    表示字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符。

  • precision和scale

    precision属性和scale属性表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数。

多对多关系
@ManyToMany

manyToMany需要和**@JoinTable**表结合使用,ManyToMany总是使用中间关系连接表来存储关系。

@JoinTable

通过表关联的方式来映射一对多或者多对多的关系时,要使用@JoinTable这个标记

  • name属性为连接两个表的表名称

  • joinColumns 主表的外键

  • inverseJoinColumns 关联表的外键

    @ManyToMany
    @JoinTable(name = "user_role",joinColumns={@JoinColumn(name="user_id")},inverseJoinColumns={@JoinColumn(name = "role_id")})
    private List<SystemRole> systemRoles;
    

延迟加载

延迟加载的禁用:lazy=“false”

  • class的延迟加载

    Session.load()方法默认延迟加载,如果是指false。即使使用load方法也无法延迟加载

    <class name="User" table="t_user" lazy="true">
    </class>
    

    如果在session关闭过来再去访问类的成员,将抛出错误,不能调用代理去查询数据

  • 集合的延迟加载(针对一对多,多对多)

    lazy默认延迟加载,当lazy=true时获取集合的大小时会查询出所有的数据然后获取总数,

    当值为extra时,会发出 count(*) sql语句 获取数据大小,当再次获取具体数据时再发出select语句

    类上的lazy=fasle 设置 不会影响集合上的lazy=true设置

    <set name="roles" table="emp_role" cascade="save-update" lazy="extra">
           
      <key column="emp_num"></key>
      <many-to-many column="role_id" class="Role"></many-to-many>
    </set>
    
  • 单端的延迟加载(针对一对一,多对一),默认 lazy=“proxy” 启用延迟加载,no-proxy:当get方法用类属性时才发sql,否则不发出sql

    <one-to-one  name="emp" constrained="true" lazy="proxy" />
    

    在单端的延迟加载中,类上禁止了延迟加载lazy="proxy"则无效

hibernate查询

HQL查询
基本查询
Session session = HibernateUtil.getSession();
// String hql ="select u from User u"; hql中没有*语法,查询所有字段
String hql ="from User";
//创建查询对象
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
    System.out.println(user);
}
单列查询(String类型list)

只查询一列返回的是一个string的list

Session session = HibernateUtil.getSession();
String hql ="select u.uname from User u";
//创建查询对象
Query query = session.createQuery(hql);
List<String> list = query.list();
for (String name : list) {
    System.out.println(name);
}
多列查询(Object数组)
Session session = HibernateUtil.getSession();
String hql ="select u.uname,u.gender from User u";
//创建查询对象
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for (Object[] objects : list) {
    System.out.println(objects[0]);
    System.out.println(objects[1]);
}
分页查询
Session session = HibernateUtil.getSession();
String hql ="select u from User u";
//创建查询对象
Query query = session.createQuery(hql);
//开始行数,第一条从0开始 startNum = (pageNumber-1)* pageSize
query.setFirstResult(0);
//每页大小
query.setMaxResults(2);
List<User> list = query.list();
for (User name : list) {
    System.out.println(name);
}
限定查询
Session session = HibernateUtil.getSession();
String hql ="select u from User u where u.gender=?";
//创建查询对象
Query query = session.createQuery(hql);
query.setParameter(0,2);
List<User> list = query.list();
for (User name : list) {
    System.out.println(name);
}
//传值类型2
String hql ="select u from User u where u.gender=:gender";
//创建查询对象
Query query = session.createQuery(hql);
query.setParameter("gender",2);
List<User> list = query.list();
统计查询(唯一单列查询)

统计查询

Session session = HibernateUtil.getSession();
String hql ="select count(*) from User u";
//创建查询对象
Query query = session.createQuery(hql);
Object o = query.uniqueResult();
System.out.println(o);

统计查询查询

最大值

String hql ="select max(u.userId) from User u";

最小值

String hql ="select min(u.userId) from User u";

平均值

String hql ="select avg(u.gender) from User u";

求和

 String hql ="select sum(u.gender) from User u";
分组统计查询
Session session = HibernateUtil.getSession();
String hql ="select count(*),u.gender from User u group by u.gender";
//创建查询对象
Query query = session.createQuery(hql);
List<Object[]> objects = query.list();
for (Object[] object : objects) {
    System.out.println(object[0]);
    System.out.println(object[1]);
}
排序
String hql ="select u from User u order by u.gender desc";
模糊查询
String hql ="select u from User u  where u.gender like '%2%';
QBC查询
基本查询
Session session = HibernateUtil.getSession();

Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for (User user : list) {
    System.out.println(user);
}
查询单列

列名为对象属性名

Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.property("uname"));
List<String> list = criteria.list();
for (String user : list) {
    System.out.println(user);
}
查询多列

projectionList 类的应用

ProjectionList projectionList = Projections.projectionList();
PropertyProjection uname = Projections.property("uname");
PropertyProjection gender = Projections.property("gender");
projectionList.add(uname);
projectionList.add(gender);

criteria.setProjection(projectionList);
List<Object[]> list = criteria.list();
统计查询

主要是 Projections 的静态方法

  • 总行数

    Criteria criteria = session.createCriteria(User.class);
    criteria.setProjection(Projections.rowCount());
    Object list = criteria.uniqueResult();
    
  • 最大值

    criteria.setProjection(Projections.max("gender"));
    Object list = criteria.uniqueResult();
    
  • 分组统计

    Criteria criteria = session.createCriteria(User.class);
    
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add(Projections.rowCount());
    projectionList.add(Projections.groupProperty("gender"));
    
    criteria.setProjection(projectionList);
    
    List<Object[]>list = criteria.list();
    for (Object[] objects : list) {
        System.out.println(Arrays.toString(objects));
    }
    
排序
Criteria criteria = session.createCriteria(User.class);
criteria.addOrder(Order.asc("gender"));
List<User>list = criteria.list();
分页
Criteria criteria = session.createCriteria(User.class);
criteria.addOrder(Order.asc("gender"));
//从第几行开始
criteria.setFirstResult(0);
//没页多少条
criteria.setMaxResults(2);
限定查询

Restrictions 静态 限定api

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

Criterion gender = Restrictions.eq("gender", 2);
criteria.add(gender);
逻辑语句and&&or

Restrictions 的and 和 or api 将传入的 Criterion 条件 以 and / or 的方式链接

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

Criterion gender = Restrictions.eq("gender", 2);
SimpleExpression userId = Restrictions.gt("userId", 3);
Criterion and = Restrictions.and(userId,gender);
criteria.add(and);
SQL查询
Session session = HibernateUtil.getSession();
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
}

继承映射

单表继承映射

继承映射不支持子类的load查询,但是可以get查询

多个实体存在一张表中使用 使用某个字段区分 不同实体内存在不同的字段

image-20200707105627083
<class name="Animal" table="t_animal">

        <id name="anId" column="an_id">
            <generator class="native"></generator>
        </id>
        <!--   子类鉴别器 在单表中加入一列来区别子类 必须放前面 -->
        <discriminator column="type" type="string"/>
        <property name="anName" column="an_name"/>
        <property name="gender"/>
        
        <!--  子类配置
             name:子类的类名
             discriminator-value:区分子类的值
        -->
         <subclass name="Pig" discriminator-value="p">
            <property name="weight" column="weight"/>
         </subclass>
        <subclass name="Bird" discriminator-value="b">
            <property name="height" column="height"/>
        </subclass>
</class>
  • 插入

    Pig pig = new Pig();
    pig.setAnName("天蓬");
    pig.setWeight(200);
    pig.setGender(1);
    session.save(pig);
    
    Bird bird = new Bird();
    bird.setAnName("大鹏");
    bird.setGender(1);
    bird.setHeight(10000);
    session.save(bird);
    
  • 查询

    Pig o = (Pig) session.get(Pig.class, 1);
    System.out.println(o);
    
父子继承映射

父类一张表,子类一张表

**数据库存储方式:**共同的数据放入父表,独立的字段放入各自的表中

<class name="Animal" table="t_animal">

    <id name="anId" column="an_id">
        <generator class="native"></generator>
    </id>

    <property name="anName" column="an_name"/>
    <property name="gender"/>

    <!--
        子类映射配置
              name:子类名称
    -->
    <joined-subclass name="Pig" table="t_pig">
        <!-- key:字表 主键  -->
        <key column="pid"></key>
        <!-- 子类属性映射  -->
        <property name="weight"/>
    </joined-subclass>
    <joined-subclass name="Bird" table="t_bird">
        <key column="bid"></key>
        <property name="height"/>
    </joined-subclass>
</class>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值