hibernate总结

来源:互联网 发布:java方法重写规则 编辑:程序博客网 时间:2024/06/06 00:30
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:tablepkColumnName    valueColumnNamepkColumnValue    N+allocationSize    例子:Table=”Item_GEN”pkColumnName=”pk_key” valueColumnName=”pk_value”pkColumnValue=”Item”allocationSize=1        表名=”Item_GEN”pk_key    pk_valueItem    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 SessionFactoryMethod    openSession    getCurrentSessionSAMES    都用来获取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.Xml1.首先创建2个实体类,用@Id注解标志各主键列2.在需要单向连接的实体类中创建另一方类的属性(外键关系属性)3.在该实体类的xml配置文件中加入<many-to-onename="外键关系属性"unique="true"/>(注:(many-to-one代表多个该类实体对一个外键实体,但是设置unique唯一来表示一对一),如果单独使用<one-to-one name=”外键关系属性”/>是不会生成外键的)ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列2.在需要单向连接的实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解,如果需要自定义该列名和其它属性约束使用@JoinColumn注解该属性b)双向外键i.Xml1.首先创建2个实体类,用@Id注解标志各主键列2.在2个实体类中创建另一方类的属性(外键关系属性)3.在其中一个实体类的xml配置文件中加入<many-to-onename="外键关系属性"unique="true"/>并在另一个实体类的xml加入<one-to-onename="外键关系属性"property-ref="关联类对应的本类关联属性"/>ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列2.在2个实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解如果需要自定义该列名和其它属性约束使用@JoinColumn注解该属性(注:此时会在两个类对应表中都生成外键,如果只需要其中一个表生成外键,那么在@OneToOne注解加入属性mappedBy让另一个形成主导即可。总结:只要有双向关联,mappedBy必设)c)单双主键(很少用)i.Xml1.首先创建2个实体类,用@Id注解标志各主键列2.在其中一个或两个实体类的xml配置文件中加入3.(双)其中一个实体xml<one-to-onename="外键关系属性"constrained="true"/>如果是单向只需要在其中一个设置该节点,另一个不需要做任何其它配置4.另一个实体xml<one-to-onename="外键关系属性"property-def="关联类对应的本类关联属性"/>注:如果不设置constrainted=”true”将不会生成外键关系ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列2.在一个或两个实体类中定义另一方类的属性(外键关系属性),在外键关系属性上用@OneToOne注解如果需要自定义该列名和其它属性约束使用@PrimayKeyJoinColumn注解该属性注:貌似不会生成关系(未查找原因)d)单向联合主键(很少用)i.Anootation1.首先创建2个实体类,用@Id注解标志各主键列。再创建一个主键组件类。2.在需要被关联的实体类用@IdClass注解标识并给赋值为主键组件的的class,并在该实体类中把主键组件的属性全部写入,并用@Id注解标志。注:组件必须实现序列化接口,并重写equals和hashCode方法.3.在另一个实体类声明一个要被关联实体类的属性引用,并用@OneToOne注解标志,系统会默认生成外键列,如果需要自定义外键列名需要用@JoinColumns注解并赋值.e)中间表——少用2nd一对多a)单向i.Xml1.首先创建2个实体类.2.再“一”的一方创建多的一方的集合引用3.在“一”/“多”的一方建力xml文件,设置主键和其他属性4.在“一”的一方添加(这里假设集合为set集合)<setname="外键关系属性"><keycolumn="自定义外键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。<one-to-manyclass="外键关系属性的类名"/></set>生成的外键会在外键关系属性的类所对应的表中。5.如果需要修改外键列名,在<many-to-one/>中使用column属性修改ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列。2.再“一”的一方创建“多”的一方的集合引用,并用@OneToMany注解标志该属性3.默认创建一个中间表。如果不需要创建中间表,只需要在“多”的一方创建一个外键,那么在“一”的一方的集合引用属性上用@JoinColumn注解标注。b)多向i.Xml1.首先创建2个实体类.2.再“一”的一方创建“多”的一方的集合引用,在“多”的一方创建“一”的一方的引用3.在“一”/“多”的一方建立xml文件,设置主键和其他属性4.在“一”的一方添加(这里假设集合为set集合)<setname="外键关系属性"><keycolumn="自定义外键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。<one-to-manyclass="外键关系属性的类名"/></set>在“多”的一方添加<many-to-onename="外键关系属性"column="自定义外键关系列名"/>注:此时column值要和“一”的一方的<key/>的column值一致,不然会多生成一个外键列生成的外键会在“多”的一方所对应的表中。ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列。2.再“一”的一方创建“多”的一方的集合引用,并用@OneToMany注解标志该属性注:此时使用@OneToMany注解时建议使用mappedBy属性,否则会生产中间表再“多”的一方创建@ManyToOne注解如果需要更改外键列名使用@JoinColumn注解生成的外键会在“多”的一方所对应的表中。3rd多对一a)单向i.Xml1.首先创建2个实体类.2.再多的一方创建单的一方的引用.3.在“一”/“多”的一方建立一般的xml文件,设置主键和其他属性4.在“多”的一方添加<many-to-onename="外键关系属性"/>5.如果需要修改外键列名,在<many-to-one/>中使用column属性修改ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列。2.在“多”的一方创建单的一方的引用,并用@ManyToOne注解标志该属性3.如果需要修改外键名,用@JoinColumn注解自定义列名b)多向参考一对多双向4th多对多a)单向i.Xml1.首先创建2个实体类.2.再其中一个“多”的一方创建另一个“多”的一方的集合引用(外键关系属性)3.在双方建立xml文件,设置主键和其他属性4.在有集合引用的一方添加(这里假设集合为set集合)<setname="外键关系属性"><keycolumn="自定义集合引用所在类中主键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。<many-to-manyclass="外键关系属性的类名"column=”指定外键关系类的主键在表中的列名”/></set>ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列2.在其中一个“多”的一方创建另一个“多”的一方的集合引用,并用@ManyToMany注解标志该属性3.生成的中间表需要自定义表名,在集合属性的上使用@JoinTable注解b)多向i.Xml1.首先创建2个实体类.2.在每一方创建另一个“多”的一方的集合引用(外键关系属性)3.在双方建立xml文件,设置主键和其他属性4.在每方xml中添加(这里假设集合为set集合)<setname="外键关系属性"table=”自定义中间表名”>注:如果不自定义相同的表名,会生成2张表。所以表名要一致<keycolumn="自定义集合引用所在类中主键列名"/>注:必写column值,如果不写则会参考两表的主键,会生成主键约束。<many-to-manyclass="外键关系属性的类名"column=”指定外键关系类的主键在表中的列名”/></set>ii.Annotation1.首先创建2个实体类,用@Id注解标志各主键列2.在每一方创建另一个“多”的一方的集合引用,并用@ManyToMany注解标志该属性3.如果要指定谁来维护这张中间表,在他对应的那个类的@ManyToMany注解设置mappedBy属性这样只会建立一张中间表,不写会建立两张表。建立的表的相关属性会依赖于mappedBy设置值的那个属性上相关设置4.生成的中间表需要自定义表名,在集合属性的上使用@JoinTable注解5th集合映射a)Listb)Setc)Map6th组件映射FAQ:问:什么是组件:答:在面向对象来说,一个类其中一个属性指向另外一个对象a)XMLi.首先创建1个实体类1个组件类,用@Id注解标志实体类的主键列。ii.在实体类的xml中使用<componentname="组件属性名">    //如果组件属性有多个,那么对应写多个<property/>    <property name=”组件类属性”/></component>1.如果字段名冲突的话,在<property/>中使用column属性自定义列名b)Annotationi.首先创建1个实体类1个组件类,用@Id注解标志实体类的主键列。ii.在实体类创建该组件的引用使用@Embedded注解标志1.如果字段名冲突的话,在组件属性上用@Column注解自定义列名7th继承关系8th级联(cascade)(一)常用取值:i.XMLsave-update    --------级联增、改delete    --------级联删除all        --------级联增、删、改none        --------默认,不做级联操作ii.AnnotationCascadeTypeAll        --------级联所有操作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    ----------用于条件查询        ClassRestrictions    ----------设置约束(都是静态方法)    所有的方法的返回类型都为Criterion        Method            add(Criterion criterion)    ----------加入约束        说明:            Class----要查询数据的类名A.无约束查询Criteria criteria=session.createCriteria(Class.class);//相当于from Classfor (Objectobj : (List<Object>)criteria.list()) {System.out.println(obj);}B.带条件查询Criteria criteria=session.createCriteria(Class.class);//相当于from Classcriteria.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方式:Lazyi.实体对象延迟1.继承下:<joined-subclassname=""extends=""lazy="value">2.非继承下:<classname=""lazy="value">ii.集合延迟<setname=""cascade=""lazy="value">iii.实体属性延迟比较麻烦在xml配置上设置lazy是没有效果的需要用到第3方工具(例如hibernate3推荐的cglib,hibernate4推荐的javaassist)下面详细介绍a)cglibi.引入cglib  jar包ii.在需要延迟加载属性的实体类实现InterceptFieldEnabled接口声明一个透明对象并重写2个方法//被transient修饰的属性,不参与对象序列化和反序列化.private transient InterceptFieldCallback interceptFieldCallback;@Overridepublic InterceptFieldCallback getInterceptFieldCallback() {return interceptFieldCallback;}    @Overridepublic 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)Javaassisti.引入javaassist  jar包(hibernate4+自带)ii.在需要延迟加载属性的实体类实现FieldHandled接口声明一个透明对象并重写2个方法//被transient修饰的属性,不参与对象序列化和反序列化.private transient FieldHandler fieldHandler;@Override    public FieldHandler getFieldHandler () {return fieldHandler;}    @Overridepublic 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:在关联对象的那个属性的标签中加入lazytrue那么就会每次不会把关联数据给取出,用到这个属性时再取false直接一次把关联数据取出<setname="students"lazy=”true”>            Annotation:在外联属性上加中的关系注解上加上Fetch属性,详见Annotation中的关系映射中的@ManyToMany注解中的FetchType属性3.Join Fetch            参考查询—迫切


0 0
原创粉丝点击