hibernate总结

Hibernate Configuration(配置文件)
<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<!—数据库连接设置-->
<propertyname="connection.driver_class">com.mysql.jdbc.Driver</property>
<propertyname="connection.url"> jdbc:mysql://localhost/hibernate</property>
<propertyname="connection.username">root</property>
<propertyname="connection.password">xiehao</property>
<!-- JDBC connection pool (use the built-in) -->
<!—JDBC连接池-->
<!-- <property name="connection.pool_size">1</property> -->
<!-- SQL dialect -->
<!—数据库方言,用于针对不同数据库sql语句语法不同来创建不同的sql语句 -->
<propertyname="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 -->
<!—2级缓存-->
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<!-输出sql语句-->
<propertyname="show_sql">true</property>
<!—格式化输出sql语句-->
<property name=”format_sql”>true</property>
<!-- Drop and re-create the database schema on startup -->
<!—启动服务时对数据库的操作-->
<propertyname="hbm2ddl.auto">update</property>
<!—实体映射配置-->
<!-- <mapping resource="com/shoper/hibernate/bean/Teacher.hbm.xml"/> -->
<mappingclass="com.shoper.hibernate.bean.Teacher"/>
</session-factory>
</hibernate-configuration>

Mapping File(映射文件基本)
<?xmlversion='1.0'encoding='utf-8'?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
//package=映射实体所在的包
<hibernate-mappingpackage="com.shoper.hibernate.bean">
//table=”表名” name=”实体名”
<classtable="teacher"name="Teacher" >
单一主键{
//id主键列、generator设置自增
Oracle{
<idname="id"column="teacher_id"type="java.lang.Integer">
<generatorclass="sequence">
<paramname="sequence">SEQ_TEACHER_ID</param>
</generator>
</id>
}
Mysql{
<idname="id"column="teacher_id"type="java.lang.Integer">
<generatorclass="sequence">
<paramname="sequence">SEQ_TEACHER_ID</param>
</generator>
</id>
}
自动判断{
    <idname="id"column="teacher_id"type="java.lang.Integer">
<generatorclass="native"></generator>
</id>
}
也可以使用UUID{//注:UUID字段类型必须是String
<idname="id"column="teacher_id"type="java.lang.String">
<generatorclass="uuid"></generator>
</id>
}
}
联合(复合)主键{
//name=复合主键组件在实体类中的属性  class=复合主键组件类所在路径
    <composite-idname="pk"class="com.shoper.hibernate.bean.PK">
    //如果复合主键有多个主键列,就多次写key-property节点
    //name=复合主键类对应的属性
        <key-propertyname="id"/>
        <key-propertyname="name"/>
    </composite-id>    
注:复合主键组件类必须实现Serializable接口并且重写equals和hashCode方法
}
//以下是非主键列column对应列名 type实体类属性的数据类型,length对应数据库中的长度
//not-null非空约束
<propertyname="name"column="teacher_name"type="java.lang.String"length="16"not-null="true"/>
<propertyname="age"column="age"type="java.lang.Integer"length="2"/>
<propertyname="title"column="title"type="java.lang.String"length="200"/>
<propertyname="empDate"column="empDate"type="java.util.Date"/>
</class>
</hibernate-mapping>
XML(映射文件其它)
<one-to-one/>
                            ----用于一对一关联
常用属性:
    String name        ----指定关联的外键关系的属性
    String property-ref    ----指定关联的类的本类属性,把外键指定给关联的类的表中
    Booleanconstrained    ----指定是否生成约束关系。
------------------------------------------------------------------------------------------------
<many-to-one/>
                            ----用于多对一关联
常用属性:
    String name        ----指定关联的外键关系的属性
    String unique        ----指定该键是否唯一
------------------------------------------------------------------------------------------------
<set name=””>
    <key column=””/>
</set>
                            ----用于映射集合属性
常用属性:
Set  StringName        ----指定映射的集合属性名
Set  String inverse    ----指定反转对象,详情看关系映射—反转
Key Stringcascade    ----指定级联操作,详情看关系映射--级联


Annotations(注解)
@Entity(import javax.persistence.Entity)
---实体类与数据库表建立关系
@Tables(import javax.persistence.Table)
---标志设置表名
实体类和表名不一致时用name属性修改E.g:@Tables(name=”tb_xxx”);
@Basic(import javax.persistence.Basic)
                            ---标志非主键
属性上不加注解默认为该注解(非主键列)
@Column(import javax.persistence.Column)
                                -----设置列名
字段名与列名不同时,通过该注解指定@Column(name=”xxx”)
@Transient(import javax.persistence.Transient)---不需要持久化的字段
@Enumerated(import javax.persistence.Enumerated)—映射枚举类型。
value指定为
EnumType.ORDINAL---对应数据库列类型为数字类型(int|number)
EnumType.STRING---对应数据库列类型为数字类型(varchar类型长度为255)
@Temporal(import javax.persistence.Temporal)
---映射日期类型存入数据库时列类型,当值为以下时:
TemporalType.DATE---对应数据库列类型为数字类型(Date)
TemporalType.TIME---对应数据库列类型为数字类型(Time)
TemporalType.TIMESTAMP---对应数据库列类型为数字类型(TimeStamp)
@SequenceGenerator(importjavax.persistence.SequenceGenerator)
--------定义自增生成器
属性:
    name=指定序列生成器名
sequenceName=序列名
@TableGenerator(importjavax.persistence.SequenceGenerator)
                            --------定义表方式自增生成器
属性:
    name=指定表方式序列生成器名
    table=指定生成的表名
pkColumnName=指定主键列名(也就是表的一个列名)
valueColumnName=指定主键值列名(也就是表的一个列名)
pkColumnValue=指定表中数据的名
allocationSize=每次增加的值
TableName:table
pkColumnName    valueColumnName
pkColumnValue    N+allocationSize
    
例子:
Table=”Item_GEN”
pkColumnName=”pk_key” valueColumnName=”pk_value”
pkColumnValue=”Item”
allocationSize=1
        表名=”Item_GEN”
pk_key    pk_value
Item    1(每次会自动修改此值)

@GeneratedValue (importjavax.persistence.GeneratedValue)
-------自增标志列
常用属性有:
generator(用来指定主键生成器的名字,必须先定义生成器名详见@SequenceGenerator)
    strategy(指定主键生成器的策略)
常用值有:
GenerationType.AUTO---自动判断生成器的类型(默认)
GenerationType.Table---设置表方式(使用时指定生成器表名即可,表配置表方式详见@TableGenerator)
复合(联合)主键{
    需要创建组件类,实体类并有组件类属性,三种方式
①{
@Embeddable (importjavax.persistence.Embedded)
                            --注解组件类
@Id(importjavax.persistence.Id)
                            --注解组件类属性或get方法
保存时使用:
创建组件类对象,并赋值给实体类对象。
}
②{
@EmbeddedId (importjavax.persistence.Embedded)
                            --注解实体类对应的组件属性
}
③{
@IdClass (importjavax.persistence.IdClass)
                            --注解实体类
    属性:
value=指定组件类的class
@Id(importjavax.persistence.Id)
                            --注解实体类属性
注:组件属性和实体类主键属性对应,只需要在实体类属性或get方法上添加注解,组件类属性不必添加
}                    
}
    关系映射{
        @OneToOne(importjavax.persistence.OneToOne)
                                    ----注解该属性为一对一关联
            常用属性:
String mappedBy-----指定关联的本实体的属性的一方来主导这个外键,也就是外键在指定的属性所在的实体类对应的表中
        @ManyToOne(importjavax.persistence.ManyToOne)
                                    ----注解该属性为多对一关联
            常用属性:
String mappedBy-----指定关联的本实体的属性的一方来主导这个外键,也就是外键在指定的属性所在的实体类对应的表中
@OneToMany(importjavax.persistence.OneToMany)
                                    ----注解该属性为一对多关联
            常用属性:
String mappedBy-----指定关联的本实体的属性的一方来主导这个外键,也就是外键在指定的属性所在的实体类对应的表中


        @JoinColumn(importjavax.persistence.JoinColumn)
                                ----为该注解的属性在数据库表中指定一个列
            常用属性:
                String name-----指定生成列的名字
                Boolean nullable-----指定该列是否允许为空
                Boolean unique------指定该列是否唯一
                String referencedColumnName-----指定引用的列(注:通常在使用@JoinColumns注解时用)
        @PrimaryKeyJoinColumn(importjavax.persistence.PrimaryKeyJoinColumn)
                            ----为该注解的属性在设置主键关联(Bug)
        @JoinColumns(importjavax.persistence.JoinColumns)
                                ----为该注解的属性在数据库表中指定多个列
            常用属性:
                JoinColumn[] value----指定多个列,参考@JoinColumn注解
                    赋值方式
value={@JoinColumn(),@JoinColumn().....}
                (注:必须使用@JoinColumn注解的referencedColumnName属性来标明引用的外键列)
@JoinTable(importjavax.persistence.JoinTable)
                    ----为该注解的属性在数据库中生成的中间表的表命别名
    常用属性:
                String     name            ------指定生成表的名字
                @JoinColumn[]注解joinColumns    ------指定该注解所在类的主键属性在表中生成列名
                @JoinColumn[]注解inverseJoinColumns    ------指定该注解属性对应的实体类的主键(外键主键)属性在表中生成列名

        @ManyToMany(importjavax.persistence.MantToMany)
                                ----注解该属性为多对多关联
            常用属性:
                
                FetchType    fetch    ------指定读取类型
                    值
                    FetchType-LAZY    ------延迟加载
                    FetchType-ERGER    ------延迟加载

}
        

开发常用接口
−    Configuration(加载配置文件)
4.0-
    Configuration config = new Configuration().configure();
SessionFactory sf=config.buildSessionFactory();
4.0+
    Configuration config = new Configuration().configure();
ServiceRegistry serviceRegistry = newServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
SessionFactory sf=config.buildSessionFactory(serviceRegistry);

注:如果配置文件不为”hibernate.cfg.xml”要在configure()指定配置文件
−    SessionFactory(会话工厂)





Two ways for get session by SessionFactory
Method    openSession    getCurrentSession
SAMES    都用来获取session对象
    
    
    
DIFFERENCES    每次创建新的session,需要手动关闭session    如果有session就使用旧的,没有就创建新的.不需要手动关闭session
        
        
        
        
注:使用getCurrentSession需要在主配置文件配置current_session_context_class新版本默认thread


附:current_session_context_class常用2个值用途
    jta     -----Java Transaction API
从分布式建立事务,用于分布式管理跨数据库平台的事务处理,往往需要Jboss等应用容器支持.Tomcat之类需要第三方类库支持。
    thread    -----Thread
从数据库建立事务。处理单个数据库时使用
−        Session (会话)
用于对数据库增删改查等操作
            常用方法:
                ---方法见下页








常用方法    说明
    
save(Object)    如果未指定主键自动生成,保存一个对象,必须有主键,但是该对象主键不能是存在的(包括非①Transient状态对象),如果未指定则传入的主键值不能重复
    
delete(Object)    删除一个数据库的某个数据.传入对象必须有主键值
    
load(②Class,③Serializable)    获取数据库表中的某行数据,得到一个对象,该对象是一个代理对象,在通过该对象get属性时才会发送sql语句获取值。具有延迟初始化特性(如果配置了延迟状态)。如果关闭session则不能get属性值。如果在同一个session中load两次同一个主键的对象,第2次直接从缓存中取不再查询数据库。
    
get(Class,Serializable)    获取数据库表中的某行数据,得到一个对象。多次get同一主键的对象会先从缓存中查找。
    
update(Object)    更新一个对象,该对象必须有主键值
    
merge(Object)    合并一个对象到数据库,必须有主键值,相同的数据不更新,不同数据则进行同步,执行先从数据库查询一次,再比较后更新,影响性能.
    
clear()    清空缓存(例如清空连续load或get之间的缓存)
    
flush()    强制把缓存中的信息输入到数据库具体flush调用由flushMode控制
    
    
注:①Transient详见对象的三种状态②Class实体类字节码(表对应的实体类)③Serializable实现该接口的变量(主键属性)
补充:getNamedQuery()        创建一个命名查询;
−    Query(查询)
详见查询

对象三种状态
    对象三种状态
1.Transient(瞬时)
−与session无联系,不存在与数据库相对应的主键
2.Persistent(持久)
−与session有联系存在与数据库相对应的主键
3.Detached(托管)
−与session没有联系存在数据库相对应的主键
判断三种状态的关键
有没有ID,ID在数据库中有没有,在内存中有没有(session缓存)

三种状态的转换关系


关系映射
1st一对一
a)单向外键
i.Xml
1.首先创建2个实体类,用@Id注解标志各主键列
2.在需要单向连接的实体类中创建另一方类的属性(外键关系属性)
3.在该实体类的xml配置文件中加入
<many-to-onename="外键关系属性"unique="true"/>
(注:(many-to-one代表多个该类实体对一个外键实体,但是设置unique唯一来表示一对一),如果单独使用<one-to-one name=”外键关系属性”/>是不会生成外键的)
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列
2.在需要单向连接的实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解,如果需要自定义该列名和其它属性约束使用@JoinColumn注解该属性
b)双向外键
i.Xml
1.首先创建2个实体类,用@Id注解标志各主键列
2.在2个实体类中创建另一方类的属性(外键关系属性)
3.在其中一个实体类的xml配置文件中加入
<many-to-onename="外键关系属性"unique="true"/>
并在另一个实体类的xml加入
<one-to-onename="外键关系属性"property-ref="关联类对应的本类关联属性"/>
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列
2.在2个实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解如果需要自定义该列名和其它属性约束使用@JoinColumn注解该属性
(注:此时会在两个类对应表中都生成外键,如果只需要其中一个表生成外键,那么在@OneToOne注解加入属性mappedBy让另一个形成主导即可。总结:只要有双向关联,mappedBy必设)

c)单双主键(很少用)
i.Xml
1.首先创建2个实体类,用@Id注解标志各主键列
2.在其中一个或两个实体类的xml配置文件中加入
3.(双)其中一个实体xml<one-to-onename="外键关系属性"constrained="true"/>如果是单向只需要在其中一个设置该节点,另一个不需要做任何其它配置
4.另一个实体xml<one-to-onename="外键关系属性"property-def="关联类对应的本类关联属性"/>
注:如果不设置constrainted=”true”将不会生成外键关系
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列
2.在一个或两个实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解如果需要自定义该列名和其它属性约束使用@PrimayKeyJoinColumn注解该属性
注:貌似不会生成关系(未查找原因)
d)单向联合主键(很少用)
i.Anootation
1.首先创建2个实体类,用@Id注解标志各主键列。再创建一个主键组件类。
2.在需要被关联的实体类用@IdClass注解标识并给赋值为主键组件的的class,并在该实体类中把主键组件的属性全部写入,并用@Id注解标志。注:组件必须实现序列化接口,并重写equals和hashCode方法.
3.在另一个实体类声明一个要被关联实体类的属性引用,并用@OneToOne注解标志,系统会默认生成外键列,如果需要自定义外键列名需要用@JoinColumns注解并赋值.
e)中间表——少用
2nd一对多
a)单向
i.Xml
1.首先创建2个实体类.
2.再“一”的一方创建多的一方的集合引用
3.在“一”/“多”的一方建力xml文件,设置主键和其他属性
4.在“一”的一方添加(这里假设集合为set集合)
<setname="外键关系属性">
<keycolumn="自定义外键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。
<one-to-manyclass="外键关系属性的类名"/>
</set>
生成的外键会在外键关系属性的类所对应的表中。
5.如果需要修改外键列名,在<many-to-one/>中使用column属性修改
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列。
2.再“一”的一方创建“多”的一方的集合引用,并用@OneToMany注解标志该属性
3.默认创建一个中间表。如果不需要创建中间表,只需要在“多”的一方创建一个外键,那么在“一”的一方的集合引用属性上用@JoinColumn注解标注。
b)多向
i.Xml
1.首先创建2个实体类.
2.再“一”的一方创建“多”的一方的集合引用,在“多”的一方创建“一”的一方的引用
3.在“一”/“多”的一方建立xml文件,设置主键和其他属性
4.在“一”的一方添加(这里假设集合为set集合)
<setname="外键关系属性">
<keycolumn="自定义外键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。
<one-to-manyclass="外键关系属性的类名"/>
</set>
在“多”的一方添加
<many-to-onename="外键关系属性"column="自定义外键关系列名"/>
注:此时column值要和“一”的一方的<key/>的column值一致,不然会多生成一个外键列
生成的外键会在“多”的一方所对应的表中。
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列。
2.再“一”的一方创建“多”的一方的集合引用,并用@OneToMany注解标志该属性
注:此时使用@OneToMany注解时建议使用mappedBy属性,否则会生产中间表
再“多”的一方创建@ManyToOne注解如果需要更改外键列名使用@JoinColumn注解
生成的外键会在“多”的一方所对应的表中。

3rd多对一
a)单向
i.Xml
1.首先创建2个实体类.
2.再多的一方创建单的一方的引用.
3.在“一”/“多”的一方建立一般的xml文件,设置主键和其他属性
4.在“多”的一方添加<many-to-onename="外键关系属性"/>
5.如果需要修改外键列名,在<many-to-one/>中使用column属性修改
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列。
2.在“多”的一方创建单的一方的引用,并用@ManyToOne注解标志该属性
3.如果需要修改外键名,用@JoinColumn注解自定义列名
b)多向
参考一对多双向
4th多对多
a)单向
i.Xml
1.首先创建2个实体类.
2.再其中一个“多”的一方创建另一个“多”的一方的集合引用(外键关系属性)
3.在双方建立xml文件,设置主键和其他属性
4.在有集合引用的一方添加(这里假设集合为set集合)
<setname="外键关系属性">
<keycolumn="自定义集合引用所在类中主键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。
<many-to-manyclass="外键关系属性的类名"column=”指定外键关系类的主键在表中的列名”/>
</set>
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列
2.在其中一个“多”的一方创建另一个“多”的一方的集合引用,并用@ManyToMany注解标志该属性
3.生成的中间表需要自定义表名,在集合属性的上使用@JoinTable注解
b)多向
i.Xml
1.首先创建2个实体类.
2.在每一方创建另一个“多”的一方的集合引用(外键关系属性)
3.在双方建立xml文件,设置主键和其他属性
4.在每方xml中添加(这里假设集合为set集合)
<setname="外键关系属性"table=”自定义中间表名”>注:如果不自定义相同的表名,会生成2张表。所以表名要一致
<keycolumn="自定义集合引用所在类中主键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。
<many-to-manyclass="外键关系属性的类名"column=”指定外键关系类的主键在表中的列名”/>
</set>
ii.Annotation
1.首先创建2个实体类,用@Id注解标志各主键列
2.在每一方创建另一个“多”的一方的集合引用,并用@ManyToMany注解标志该属性
3.如果要指定谁来维护这张中间表,在他对应的那个类的@ManyToMany注解设置mappedBy属性
这样只会建立一张中间表,不写会建立两张表。建立的表的相关属性会依赖于mappedBy设置值的那个属性上相关设置
4.生成的中间表需要自定义表名,在集合属性的上使用@JoinTable注解
5th集合映射
a)List
b)Set
c)Map
6th组件映射
FAQ:
问:什么是组件:
答:在面向对象来说,一个类其中一个属性指向另外一个对象
a)XML
i.首先创建1个实体类1个组件类,用@Id注解标志实体类的主键列。
ii.在实体类的xml中使用
<componentname="组件属性名">
    //如果组件属性有多个,那么对应写多个<property/>
    <property name=”组件类属性”/>
</component>
1.如果字段名冲突的话,在<property/>中使用column属性自定义列名
b)Annotation
i.首先创建1个实体类1个组件类,用@Id注解标志实体类的主键列。
ii.在实体类创建该组件的引用使用@Embedded注解标志
1.如果字段名冲突的话,在组件属性上用@Column注解自定义列名

7th继承关系
8th级联(cascade)
(一)常用取值:
i.XML
save-update    --------级联增、改
delete    --------级联删除
all        --------级联增、删、改
none        --------默认,不做级联操作
ii.Annotation
CascadeType
All        --------级联所有操作
Detach    --------级联托管操作
Merge    --------级联组合操作(save+update)
Persist    --------级联持久操作
Refresh    --------级联刷新操作
Remove    --------级联移除操作

(二)介绍和用法:
        用于“多”对“多”(包括“一”对“多”)关系中修改一方数据,在与之对应的表中自动进行级联操作。
1.XML方式:
    <many-to-one name=" "class=" "cascade="value"/>
<set name=" "table=""cascade="value">
等任何有关联的节点标签中使用cascade属性即可
注value查看常用取值
2.Annotation(注解)方式
            @ManyToOne注解等任何有关联的注解中使用cascade属性即可
        注:cascade取值查看常用取值
9th反转(Inverse)    
(一)常用取值:
True-----设置允许反转
False-----设置不允许反转
(二)介绍和用法:
在“多”对“多”(“一”对“多”)关系中,如果要把对数据的维护权交给某个实体,那么就让该实体的维护属性上加上反转属性
Tip:一般用在一对多的一方,写inverse="true"
强烈建议,关系的维护总是由多方来做

1.XML方式:
            <set name=" " table=" " inverse="value">
2.Annotation(注解)方式:
后续…..
10th读取(Fetch)
参考性能优化的延迟
查询
    查询接口:Query
        方法:
            List     list()-----获取多行数据,不会去查询缓存的信息(无2级缓存下)_所有对象全部取出
            Iterator<>    iterate()-----获取多行数据,会先查询缓存的信息_先取ID,当用到其他属性时才取
Object    uniqueResult()-----获取单行唯一的数据

HQL:
Class-----查询的实体类
Field-----查询的属性
1.单表查询
a)全部数据
i.iterate()
String hql = "from Class";
Query query = session.createQuery(hql);
Iterator<Object>itemItr = query.iterate();
for (;itemItr.hasNext();) {
Grade item = itemItr.next();
System.out.println(item);
}
ii.list()
2.
            String hql = "from Class";
            Query query = session.createQuery(hql);
            List<Object>items = query.list();
            for (Object item : items) {
            System.out.println(item);
}
Object数据类型可根据你参数的实际类型更改
a)部分数据
i.单个部分数据
String hql ="selectFieldfromClass";
Query query = session.createQuery(hql);
List<Object> items = query.list();
for(Object item : itmes) {
System.out.println(item);
}    
list()方法会把所有行数据封装成一个list集合

ii.多个部分数据
String hql ="selectField1,Field2fromClass";
Query query = session.createQuery(hql);
List<Object[]> items = query.list();
for(Object[] item : itmes) {
//第1个参数会对应Object数组的0号下标,依次类推
System.out.println(item[0]+item[1]);
}
查询多个属性时,list()方法会自动把每行所有的属性封装成数组
3.条件查询
a)不带参
String hql = "from Class where Field= ?";
Query query = session.createQuery(hql);
List<Object>items = query.list();
for (Object item : items) {
System.out.println(item);
}
b)带参数
i.参数形式“?”
String hql = "from Classwhere Field= ?";
Query query = session.createQuery(hql);
query.setInteger(0, 1);
//注根据Field的类型来调用不同set方法
//第1个参数为?的下标值从0开始
//第2个参数为传递的值
List<Object>items = query.list();
for (Object item : items) {
System.out.println(item);
}
ii.参数形式“:”
1.属性参数
String hql = "from Classwhere  Field1= :abc and Field2 =:acd";
Query query = session.createQuery(hql);
query.setInteger("abc", 1);
query.setString("acd","str");
//注根据Field的类型来调用不同set方法
//第1个参数为你设置的参数名:取名规则(“:xxx”),在”:”加自定义参数名即可
//第2个参数为你传递的值
List<Object>items = query.list();
for (Objectitem : items) {
System.out.println(item);
}
2.对象参数
//这里用Student类举个例
Student stu = newStudent();
stu.setId(1);
stu.setName("xiaobai");
String hql = "from Studentwhere id = :id and name = :name";
Query query = session.createQuery(hql);
query.setProperties(stu);
//使用setProperties()方法
//内部会反射来查找自定义参数名,并设置参数的值
//这里虽然没必要指定name属性,只是用来演示多参数传递
//比如stu对象中的name属性会对“:name”参数
List<Student>students = query.list();
for (Studentstudent : students) {
System.out.println(student);
}
3.    集合参数
Map<String, Object> map = new HashMap<String, Object>();
map.put("a", 1);
map.put("b", "args");
String hql = "from Class where Field1 = :a and Field2= :b";
Query query = session.createQuery(hql);
query.setProperties(map);
//使用setProperties()方法
//此时map数据的个数至少要和自定义参数的个数相同
//且key键的得和自定义参数的名字相同
//内部会通过map的key键来反射对应自定义参数,并设置值
//比如map对象中有key为“a”的一组数据那么会去对应自定义参数“:a”去//设置值
List<Object>items = query.list();
for (Object item : items) {
System.out.println(item);
}
4.数组参数
//在某范围内的查询使用
String hql = "from Class where Field in (:field)";
Query query = session.createQuery(hql);
query.setParameterList("field", newObject[] {1,2,3,4});
//使用setPatameterList()方法.
//第1个参数为自定义参数名
//第2个参数为指定的值
//此时会把数组的值放到“in()”括号里
List<Object> items = query.list();
for (Object item : items) {
System.out.println(item);
}
5.未知参数类型
String hql = "from Classwhere Field= :field";
Query query = session.createQuery(hql);
query.setParameter("field","field");
//当不确定传入的参数的类型时,可以使用setParameter();
//如果有多个参数需要指定,就多次set即可
//第1个参数为自定义参数名
//第2个参数为对应的值
List<Object>items = query.list();
for (Objectitem : itmes) {
System.out.println(item);
}
6.区间查询
String hql = "from Grade where Field between :begin and :end";
Query query = session.createQuery(hql);
query.setInteger("begin", 1);
query.setInteger("end", 3);
List<Object>items = query.list();
for (Objectitem : items) {
System.out.println(item);
4.}
1.比较符
//用年级Grade类举例
String hql = "from Grade where gradeId > :gradeId";
Query query = session.createQuery(hql);
query.setInteger("gradeId", 1);
List<Grade> grades = query.list();
for (Grade grade : grades) {
System.out.println(grade);
}
2.内连接
//拿Grade类举例g.classes为grade类中的一个集合属性包含该年级对应的班级
//distinct()函数为去掉重复数据
//此时的内连查询的类必须跟from的类有外键关系的属性才行,否则会抛异常
//比如直接写Class类也是错的,必须是grade类的中Class类型的属性才行,且有
外键关联

a)普通
在获取班级时需要再一次查询数据库获取数据
String hql = "select distinct(g) from Grade g inner join g.classes c";
Query query = session.createQuery(hql);
List<Grade> grades = query.list();
for (Grade grade : grades) {
System.out.println(grade);
for (Class clazz : grade.getClasses()) {
System.out.println(clazz);
}
}
b)迫切
在获取年级时就获取班级信息
String hql = "select distinct(g) from Grade g inner join fetch g.classes c";
Query query = session.createQuery(hql);
List<Grade> grades = query.list();
for (Grade grade : grades) {
System.out.println(grade);
for (Class clazz : grade.getClasses()) {
System.out.println(clazz);
}
}
                //总结
                迫切就是在查询本表的同时,也会把当前这行数据主键对应的外键表的数据一同查询出来
                举例说明,当查询出gradeId为1时,就会去Class表中把gradeId为1的数据查出来,
                当查询出gradeId为2时,就会去Class表中把gradeId为2的数据查出来,依次类推。
3.外连接
所有的使用方法与内连接一样
a)左外
通过left join关键字
b)右外
通过right join关键字
c)左右迫切查询
在join后使用fetch关键字
注:在IT界中没人提到右外迫切查询,但是实际中是存在的
4.分页查询
Integer pageIndex = 2;
//查询页数
Integer pageSize = 3;
//每页数据量
String hql = "from Class";
Query query = session.createQuery(hql);
query.setFirstResult(pageSize * (pageIndex - 1));
//设置开始编号
query.setMaxResults(pageSize);
//设置数据量
List<Object>items = query.list();
for (Objectitem : itmes) {
System.out.println(item);
}
得到的结果为FirstResult—MaxResultes之间的数据
5.分组排序
不再多写,百度查询
6.单一结果查询
//用查询年级的例子演示
String hql=" select count(gradeId) from Grade";
Query query=session.createQuery(hql);
Integer integer=Integer.parseInt(query.uniqueResult().toString());
uniqueResult()方法只能用于获取单个数据
System.out.println(integer);
7.命名查询
//用查询年级的例子演示
a)首先在XML中配置
<queryname="hqlByGradeId">//name给HQL语句命一个名
<!-- 元数据标记  -->
<![CDATA[from Grade where gradeId = :gradeId]]>//HQL语句
</query>
b)在代码中使用getNamedQuery()方法
Query query = session.getNamedQuery("hqlByGradeId");//传入XML中定义的名字
query.setInteger("gradeId", 1);//为HQL语句自定义参数赋值
Grade grade = (Grade)query.uniqueResult();
//用uniqueResult()方法获取唯一数据(一个Grade数据)
System.out.println(grade);
SQL:
    创建SQLQuery方法
        Query session.createSQLQuery();
    其他方法不做介绍,简单写下命名查询
命名查询
1.首先在XML中配置
<sql-queryname="sqlByGradeId">//name给SQL语句命一个名
<!-- 支持?占位符和命名参数 -->
<![CDATA[select g.* from tb_grade g where gradeId = :gradeId]]>//SQL语句
<returnalias="g"class="Grade"/>
//因为sql不是HQL,不知道查询的结果该封装到哪个类中,所以要指定,alias为别//名(查询时为列生成的别名);
//class为封装类的类称
</query>
2.在代码中使用getNamedQuery()方法
Query query = session.getNamedQuery("sqlByGradeId");//传入XML中定义的名字
query.setInteger("gradeId", 1);//为HQL语句自定义参数赋值
Grade grade = (Grade)query.uniqueResult();
//用uniqueResult()方法获取唯一数据(一个Grade数据)
System.out.println(grade);
QBC_Query by criteria(了解)
    Interface 
Criteria criteria    ----------用于条件查询
        Class
Restrictions    ----------设置约束(都是静态方法)
    所有的方法的返回类型都为Criterion
        Method
            add(Criterion criterion)    ----------加入约束
        说明:
            Class----要查询数据的类名
A.无约束查询
Criteria criteria=session.createCriteria(Class.class);//相当于from Class
for (Objectobj : (List<Object>)criteria.list()) {
System.out.println(obj);
}
B.带条件查询
Criteria criteria=session.createCriteria(Class.class);//相当于from Class
criteria.add(Restrictions.idEq(1));//筛选id为1的条件,方法很多不过多介绍
for (Objectobj : (List<Object>)criteria.list()) {
System.out.println(obj);
}
C.外键关联查询
//以学生老师类做示例
//老师类中有学生的集合students。
//老师跟学生有外键关系
Criteria criteria=session.createCriteria(Teacher.class)
.add(Restrictions.gt("id",1))//设置本类约束Teacher类中的id约束
.createCriteria("students")//连接外键关系的属性
.add(Restrictions.gt("id", 1));//设置外键关系属性的约束Student类中的id约束
for(Object obj : criteria.list()) {
System.out.println(obj);
}
QBE_Query by Example(了解)
    创建Example实例用Example的静态方法create();
        //以老师类做示例,
        Teacher teacher=new Teacher();//创建老师例子对象
        teacher.setName("T_");//设置这个对象的Name属性为”T_”
        Example example=Example.create(teacher).ignoreCase().enableLike();
        //创建一个例子,并指定到teacher对象,设置比较时忽略大小写,并开启模糊查询
        Criteria criteria=session.createCriteria(Teacher.class)
                .add(example);//把例子传给Criteria的约束
                ;
        for (Object obj : criteria.list()) {
            System.out.println(obj);
        }


性能优化
A.延迟(Lazy|Fetch)
常用取值:
True-----设置允许延迟加载
False-----设置不允许延迟加载
(三)介绍和用法:
在获取某个实体对象数据的时候,通常不需要立马读取数据出来,那么可以设置该对象实体lazy延迟属性,只有当在获取该对象的某个值的时候才会真正去执行
1.XML方式:
Lazy
i.实体对象延迟
1.继承下:
<joined-subclassname=""extends=""lazy="value">
2.非继承下:
<classname=""lazy="value">
ii.集合延迟
<setname=""cascade=""lazy="value">
iii.实体属性延迟
比较麻烦在xml配置上设置lazy是没有效果的需要用到第3方工具(例如hibernate3推荐的cglib,hibernate4推荐的javaassist)下面详细介绍
a)cglib
i.引入cglib  jar包
ii.在需要延迟加载属性的实体类实现InterceptFieldEnabled接口声明一个透明对象并重写2个方法
//被transient修饰的属性,不参与对象序列化和反序列化.
private transient InterceptFieldCallback interceptFieldCallback;
@Override
public InterceptFieldCallback getInterceptFieldCallback() {
return interceptFieldCallback;
}    
@Override
public void setInterceptFieldCallback(InterceptFieldCallback interceptFieldCallback) {
this.interceptFieldCallback = interceptFieldCallback;
}    
iii.再把需要延迟加载的属性的get和set方法修改为
Private String XXX;
public String getXXX() {
if (interceptFieldCallback == null) {
return XXX;
} else {
return (String)interceptFieldCallback.readObject(this, "该属性对应的列名", XXX);
}
}
public void setXXX(String XXX) {
if (interceptFieldCallback == null) {
this.XXX = XXX;
} else {
this.XXX = (String)interceptFieldCallback.writeObject(this, "该属性对应的列名", this.XXX, XXX);
}
}
b)Javaassist
i.引入javaassist  jar包(hibernate4+自带)
ii.在需要延迟加载属性的实体类实现FieldHandled接口声明一个透明对象并重写2个方法
//被transient修饰的属性,不参与对象序列化和反序列化.
private transient FieldHandler fieldHandler;
@Override    
public FieldHandler getFieldHandler () {
return fieldHandler;
}    
@Override
public void setFieldHandler (FieldHandler fieldHandler) {
this. fieldHandler = fieldHandler;
}
iii.再把需要延迟加载的属性的get和set方法修改为
Private String XXX;
public String getXXX() {
if (fieldHandler == null) {
return XXX;
} else {
return (String) fieldHandler.readObject(this, "该属性对应的列名", XXX);
}
}
public void setXXX(String XXX) {
if (fieldHandler== null) {
this.XXX = XXX;
} else {
this.XXX = (String) fieldHandler.writeObject(this, "该    对应的列名", this.XXX, XXX);
}
}            
2.Annotation(注解)方式:
Fetch
常用属性:
    FetchType LAZY-----懒惰
FetchType EAGER-----渴望
--设置成Lazy后不会立刻加载关联对象的数据
--这只成EAGER会立刻加载关联对象的数据

B.缓存(cache)
FAQ:
1.什么是缓存?
缓存是指临时文件交换区,电脑把最常用的文件从存储器里提出来临时放在缓存里。
−一级缓存(Session cache)
默认缓存,例如load()方法之间的缓存。
−二级缓存(SessionFactory cache)
配置缓存文件
需要第3方jar包提供
−查询缓存(Query cache)
重复查询才能去2级缓存里找,不重复不会。
Query开启二级缓存:
    1.<property name=”cache.use.query.cache”>true</property>
    2.Query.serCachable(true);
此时便能跨session进行缓存

面试注重点:
一、N+1:
说明:
如果在一个对象里,关联了另一个对象,XML(lazy为勤快)Annotation(FetchType.erger)。取关联对象的时,关联对象都会再发一条sql语句取出来。如果有N条那么发送N条
解决方案:
1.    BatchSize
            XML:
在关联对象的那个属性的标签中加入batch-size
设置的值表示分批处理的数据为多少,3代表,每次取3条数据,加入一共10条数据,那么只会发送4次sql语句而不会发送N10条了
                <setname="students"batch-size="3">
            Annotation:
解决方案不好,不建议使用
2.    Lazy
            XML:
在关联对象的那个属性的标签中加入lazy
true那么就会每次不会把关联数据给取出,用到这个属性时再取false直接一次把关联数据取出
<setname="students"lazy=”true”>
            Annotation:
在外联属性上加中的关系注解上加上Fetch属性,详见Annotation中的关系映射中的@ManyToMany注解中的FetchType属性
3.Join Fetch
            参考查询—迫切


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值