hibernate注解

注解映射必须满足两大条件:Hibernate3.2以上版本和JSEE 5。

@Entity 类注释,所有要持久化的类都要有

Java代码

@Entity  

public class Org implements java.io.Serializable{   

}

@Entitypublic class Org implements java.io.Serializable {}

@Id 主键

Java代码

@Id  

    @GeneratedValue  

    private StringorgId;   

    private String orgName;

@Id @GeneratedValue private String orgId; private StringorgName;

@Column(name="...") 该属性对应表中的字段是什么,没有name表示一样

@Table 对象与表映射

@UniqueConstraint 唯一约束

@Version 方法和字段级,乐观锁用法,返回数字和timestamp,数字为首选

@Transient 暂态属性,表示不需要处理

@Basic 最基本的注释。有两个属性:fetch是否延迟加载,optional是否允许null

@Enumerated 枚举类型

@Temporal 日期转换。默认转换Timestamp

@Lob 通常与@Basic同时使用,提高访问速度。

@Embeddable 类级,表可嵌入的

@Embedded 方法字段级,表被嵌入的对象和@Embeddable一起使用

@AttributeOverrides 属性重写

@AttributeOverride 属性重写的内容和@AttributeOverrides一起嵌套使用

@SecondaryTables 多个表格映射

@SecondaryTable 定义辅助表格映射和@SecondaryTables一起嵌套使用

@GeneratedValue 标识符生成策略,默认Auto

表与表关系映射

@OneToOne:一对一映射。它包含五个属性:

targetEntity:关联的目标类

Cascade:持久化时的级联操作,默认没有

fetch:获取对象的方式,默认EAGER

Optional:目标对象是否允许为null,默认允许

mappedBy:定义双向关联中的从属类。

单向:

@JoinColumn:定义外键(主表会多一字段,做外键)

@OneToMany:一对多映射;@ManyToOne:多对一映射

单向一对多:

@OneToMany(cascade=CascadeType.ALL)

@JoinColumn(name="book_oid")

单向多对一:

@ManyToOne(cascade=CascadeType.ALL)

@JoinColumn(name="author_oid")

关联表格一对多:

@OneToMany(cascade=CascadeType.ALL)

@JoinTable(joinColumn={@JoinColumn(name="BOOK_OBJECT_OID")},inverseJoinColumns={@JoinColumn(name="AUTHER_OBJECT_OID")})

双向一对多或多对一:

不需要多一张表,只是使用mappedBy:使用在One一方,值为One方类名表示Many的从属类。

Java代码

@Entity  

public class Org implements java.io.Serializable{   

  

  

    //Fields       

   @Id  

   @GeneratedValue  

    private StringorgId;   

    private StringorgName;   

    @OneToMany(mappedBy ="org")   

    private List<Department>departments;   

  

    //Constructors   

...   

    // Propertyaccessors   

...   

}

@Entitypublic class Org implements java.io.Serializable { // Fields@Id @GeneratedValue private String orgId; private String orgName;@OneToMany(mappedBy = "org") privateList<Department> departments; //Constructors... // Property accessors...}

Java代码

@Entity  

public class Department implements java.io.Serializable{   

  

  

    //Fields       

   @Id  

   @GeneratedValue  

    private Stringid;   

    private Stringname;   

    @ManyToOne(fetch=FetchType.EAGER)   

    @JoinColumn(name="org_orgId")   

    private Orgorg;   

    @OneToMany(mappedBy ="department")   

    private List<Employee>employees;   

  

    //Constructors   

  

    publicList<Employee> getEmployees(){   

       returnemployees;   

     

  

    public voidsetEmployees(List<Employee>employees){   

       this.employees =employees;   

     

  

    public OrggetOrg(){   

       returnorg;   

     

  

    public voidsetOrg(Org org){   

       this.org =org;   

     

  

     

              

              

              

       

}

@Entitypublic class Department implements java.io.Serializable { //Fields @Id @GeneratedValue private String id; private String name;@ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="org_orgId")private Org org; @OneToMany(mappedBy = "department") privateList<Employee> employees; //Constructors public List<Employee>getEmployees() { return employees; } public voidsetEmployees(List<Employee>employees) { this.employees = employees; } public Org getOrg() {return org; } public void setOrg(Org org) { this.org = org; } . . .}

Java代码

@Entity  

public class Employee implements java.io.Serializable{   

  

  

    //Fields       

   @Id  

   @GeneratedValue  

    private StringemployeeId;   

    private StringemployeeName;   

    private StringpassWord;   

    private Integerage;   

    private Integersex;   

    @ManyToOne(fetch=FetchType.EAGER)   

    @JoinColumn(name="department_id")   

    private Departmentdepartment;   

  

        

    publicDepartment getDepartment(){   

       returndepartment;   

     

  

    public voidsetDepartment(Department department){   

       this.department =department;   

     

  

     

   ...   

    // Propertyaccessors   

   ...   

}

@Entitypublic class Employee implements java.io.Serializable { //Fields @Id @GeneratedValue private String employeeId; privateString employeeName; private String passWord; private Integer age;private Integer sex; @ManyToOne(fetch=FetchType.EAGER)@JoinColumn(name="department_id") private Department department;public Department getDepartment() { return department; } publicvoid setDepartment(Department department) { this.department =department; } ... // Property accessors ...}

双向多对多:@ManyToMany.单向多对多这里不在赘述(没有太多实际意义)

这个比较简单,看下代码就明白了:

Java代码

@Entity  

public class Book implements java.io.Serializable{   

   @Id  

    private intid;   

    privateStringname;   

    privatefloatmoney;   

   @ManyToMany(cascade =CascadeType.ALL)   

    privateList<Author>authors;   

       

  

    publicList<Author> getAuthors(){   

       returnauthors;   

     

    public voidsetAuthors(List<Author> authors){   

       this.authors =authors;   

     

       

        ...   

}

@Entitypublic class Book implements java.io.Serializable { @Idprivate int id; private String name; private float money;@ManyToMany(cascade = CascadeType.ALL) privateList<Author> authors; publicList<Author> getAuthors() { returnauthors; } public voidsetAuthors(List<Author> authors) {this.authors = authors; } ...}

Java代码

@Entity  

public class Author implements java.io.Serializable{   

   @Id  

    private intid;   

    privateStringname;   

    private intage;   

   @ManyToMany(mappedBy="authors")   

    privateList<Book>books;   

       

  

    publicList<Book> getBooks(){   

       returnbooks;   

     

  

    public voidsetBooks(List<Book> books){   

       this.books =books;   

     

  

        ...   

}

@Entitypublic class Author implements java.io.Serializable { @Idprivate int id; private String name; private int age;@ManyToMany(mappedBy="authors") privateList<Book> books; publicList<Book> getBooks() { return books;} public void setBooks(List<Book>books) { this.books = books; } ...}

需要注意的是:注释最好加在属性上,不要加在get方法上,那样做有时候就会出错。比如:@ManyToMany的时候就会报错!

 

注意import javax.xx.Entity,而不是org.hibernate.xx.Entity。  

Descn属性不存在于数据库中,用@Transient注明  

------------------------------------------  

1,需要: Hibernate库文件,Hibernate Annotations库,ejb3-persstence.jar(Java持久化API)  

sessionFactory=newAnnotationConfiguration().buildSessionFactory();  

------------------------------------------  

2,<bean id="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  

    <propertyname="annotatedClasses">  

     <list>  

       <value>com.onjava.modelplanes.domain.PlaneType</value>  

     </list>  

    </property>  

</bean>  

------------------------------------------  

1,@Entity  

@Table(name ="teacher_info")  

@IdClass(UUIDHexGenerator.class)   

public class UserMember implementsjava.io.Serializable  

2,@entity通过getters/setters方法访问,或直接访问他的成员变量。  

@Entity(access =AccessType.PROPERTY)  

@Entity(access =AccessType.FIELD)  

------------------------------------------  

映射标识符  

1,@Id  

@GeneratedValue(strategy =GenerationType.AUTO)  

private String id;  

2,@Id(generate=GeneratorType.SEQUENCE,generator='SEQ_STORE')  

3,@Id(generate=GeneratorType.IDENTITY)  

------------------------------------------  

映射属性  

1,@Transient  

2,@Column(name="PLANE_ID", length=80,nullable=true)  

3,@Basic(fetch =FetchType.LAZY)  

4,@Serialized凡标识@Serialized的属性将被序列化  

public Country getCountry() { ...}  

5,@Lob标识了存储对象可能是个CLOB或者BLOB。  

@Lob(type=LobType.CLOB)  

public String getFullText(){returnfullText;}  

@Lob(type = LobType.BLOB)  

public byte[] getFullCode() {returnfullCode;}  

@Version 定义乐观锁机制使用  

------------------------------------------  

关联关系:  

一、一对一:  

1,@OneToOne(mappedBy ="address")      

public User getUser(){      

     returnuser;      

    

1、两边都定义了@OneToOne,但都没有定义mappedBy,则user和address表都会生成到对方的外键,双方都是这个关系的拥有者。   

2、两边都定义了@OneToOne,如果user定义了mappedBy,则在address表生成到user的外键,address是这个关系的拥有者;如果address定义  

了mappedBy,则在user表生成到address的外键,user是这个关系的拥有者。  

  

二、一对多,多对一:  

2,@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE})  

3,@OneToMany(mappedBy="planeType",cascade=CascadeType.ALL,fetch=FetchType.EAGER)  

@OrderBy("name")  

public List<ModelPlane>getModelPlanes() {  

    returnmodelPlanes;  

 

其中定义mappedBy的是@OneToMany,也就是说One这一方是关系的拥有者。Many一方的表中生成到关联类的外键。   

  

三、@ManyToMany    

private Set authors = newHashSet<Author>();      

@ManyToMany     

public Set<Author>getAuthors(){      

returnauthors;      

      

     

private Set books = newHashSet<Book>();       

@ManyToMany(mappedBy="authors")      

public Set<Book>getBooks(){      

returnbooks;      

     

@ManyToMany会生成中间表,具体表名和字段可以通过@AssociationTable来定义,默认的就可以了,同样关系的非拥有者,需要定义mappedBy属性。  

------------------------------------------  

命名查询  

你也可以通过注解,利用@NameQueries和@NameQuery注解,如下:  

@NamedQueries(  

  

@NamedQuery(name="planeType.findAll",query="select p from PlaneTypep" ),  

@NamedQuery(name="planeType.delete",query="delete from PlaneTypewhere id=:id" )  

 

 

------------------------------------------  

内嵌对象(组件)  

@Embedded({  

  @AttributeOverride(name='iso2', column = @Column(name='bornIso2')),  

  @AttributeOverride(name='name', column =@Column(name='bornCountryName'))  

        })  

    CountrybornIn;  

   ...  

 

  

@Embeddable(access =AccessType.FIELD)  

public class Address implements Serializable{  

    Stringcity;  

    Countrynationality;  

 

  

  

@Embeddable  

public class Country implements Serializable{  

    privateString iso2;  

    privateString name;  

  

    publicString getIso2() { return iso2;}  

    public voidsetIso2(String iso2) { this.iso2 = iso2;}  

  

   @Column(name='countryName')  

    publicString getName() { return name;}  

    public voidsetName(String name) { this.name = name;}  

   ...  

 

------------------------------------------  

自定义的主键生成策略  

@javax.persistence.GeneratedIdTable(  

  name='GEN_TABLE',  

table =@Table(name='GENERATOR_TABLE'),  

    pkColumnName= 'key',  

     valueColumnName = 'hi'  

 

  

@javax.persistence.TableGenerator(  

   name='EMP_GEN',  

   tableName='GEN_TABLE',  

   pkColumnValue='EMP',  

   allocationSize=20  

 

@javax.persistence.SequenceGenerator(  

   name='SEQ_GEN',  

   sequenceName='my_sequence'  

 

packageorg.hibernate.test.metadata;  

 

school和userMember是一对多关系

importjavax.persistence.CascadeType;  

importjavax.persistence.Column;  

importjavax.persistence.Entity;  

importjavax.persistence.FetchType;  

importjavax.persistence.GeneratedValue;  

importjavax.persistence.Id;  

importjavax.persistence.OneToMany;  

importjavax.persistence.Table;  

importjavax.persistence.Temporal;  

importjavax.persistence.TemporalType;  

  

importorg.hibernate.annotations.Formula;  

importorg.hibernate.annotations.GenericGenerator;  

  

@Entity  

@Table(name ="school_info")  

public class SchoolInfo implements java.io.Serializable{  

  

   @Id  

   @GeneratedValue(generator ="system-uuid")  

   @GenericGenerator(name = "system-uuid", strategy ="uuid")  

    privateStringid;//hibernate的uuid机制,生成32为字符串  

  

    @Column(name= "actcodeId", updatable = false, nullable = true, length =36)  

    privateString actcodeId;  

  

   @Formula("select COUNT(*) fromschool_info")  

    private intcount;  

  

   @Temporal(TemporalType.TIMESTAMP)//不用set,hibernate会自动把当前时间写入  

   @Column(updatable = false, length =20)  

    private DatecreateTime;  

  

   @Temporal(TemporalType.TIMESTAMP)  

    private DateupdateTime;//刚开始我默认insertable=false,但会读取出错提示如下:  

    // Value'0000-00-00' can not be represented asjava.sql.Timestamp  

  

    //mappedBy="school"就相当于inverse=true,(mappedBy指定的是不需要维护关系的一端)  

    //应该注意的是mappedBy值对应@ManyToOne标注的属性,我刚开始写成"schoolId",让我郁闷了好一会

   @OneToMany(mappedBy = "school", cascade = CascadeType.ALL, fetch =FetchType.EAGER, targetEntity =UserMember.class)  

    //用范性的话,就不用targetEntity了  

    private Listusers = new ArrayList();  

      

 

@GeneratedValue(strategy=GenerationType.AUTO)我们常用的自增长机制,我这里采用的是hibernate的uuid生成机制.

需要注意的是import javax.xx.Entity ,而不是org.hibernate.xx.Entity。

郁闷的是我上面用到@Formula,生成的sql竟然是'select COUNT(*) from school_info asformula0_ from school_info schoolinfo0_,当然不能执行了,寻求正解中~!!!!!!!!!

UserMember.java(前面引入的包已经贴过了,下面就不贴了)

 

@Entity  

@Table(name ="teacher_info")//实体类和数据库表名不一致时,才用这个  

public class UserMember implements java.io.Serializable{  

  

   @Id  

   @GeneratedValue(generator ="system-uuid")  

   @GenericGenerator(name = "system-uuid", strategy ="uuid")  

    privateString id;  

  

   @Column(updatable = false, nullable = false, length =20)  

    privateString logonName;  

      

   @Temporal(TemporalType.TIMESTAMP)  

   @Column(updatable = false, length =20)  

    private DatecreateTime;  

  

   @Temporal(TemporalType.TIMESTAMP)  

    private DateupdateTime;  

  

   @ManyToOne(cascade = { CascadeType.MERGE})  

   @JoinColumn(name ="schoolId")  

    privateSchoolInfo school;  

   //注意该类就不用声明schoolId属性了,如果不用@JoinColumn指明关联的字段,hibernate默认会是school_id.  

  

}


最近在项目中使用 Spring 和 Hibernate 进行开发,有感于 Criteria 比较好用,在查询方法设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装。现在对 Hibernate的Criteria的用法进行总结:   Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了Criteria和DetachedCriteria。   

Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样, Criteria 是在线的,所以它是由Hibernate Session 进行创建的;而 DetachedCriteria 是离线的,创建时无需Session,DetachedCriteria 提供了 2 个静态方法 forClass(Class) 或forEntityName(Name) 进行DetachedCriteria 实例的创建。

Spring 的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria来返回查询结果。   

Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件。可以设置 FetchMode( 联合查询抓取的模式 ) ,设置排序方式。对于 Criteria 还可以设置 FlushModel (冲刷Session 的方式)和 LockMode (数据库锁模式)。下面对 Criterion 和 Projection进行详细说明。     

Criterion 是 Criteria 的查询条件。Criteria 提供了 add(Criterion criterion)方法来添加查询条件。     Criterion 接口的主要实现包括: Example 、 Junction 和 SimpleExpression 。而Junction 的实际使用是它的两个子类 conjunction 和 disjunction ,分别是使用 AND 和 OR操作符进行来联结查询条件集合。     Criterion 的实例可以通过 Restrictions 工具类来创建,Restrictions 提供了大量的静态 方法,如 eq(等于)、 ge (大于等于)、 between 等来方法的创建 Criterion 查询条件 (SimpleExpression实例)。除此之外, Restrictions 还提供了方法来创建 conjunction 和 disjunction实例,通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合 。至于 Example 的创建有所不同,Example 本身提供了一个静态方法 create(Object entity),即根据一个对象(实际使用中一般是映射到数据库的对象)来创建。然后可以设置一些 过滤条件:

Example exampleUser =Example.create(u) .ignoreCase() // 忽略大小写

.enableLike(MatchMode.ANYWHERE); // 对 String 类型的属性,无论在那里值在那里都匹配。相当于%value%  

Project 主要是让 Criteria 能够进行报表查询,并可以实现分组。 Project 主要有SimpleProjection 、 ProjectionList 和 Property 三个实现。其中SimpleProjection 和 ProjectionList 的实例化是由内建的 Projections 来完成,如提供的avg 、 count 、 max 、 min 、 sum可以让开发者很容易对某个字段进行统计查询。       

Property 是对某个字段进行查询条件的设置,如通过Porperty.forName(“color”).in (newString[]{“black”,”red”,”write”}); 则可以创建一个 Project 实例。通过 criteria 的add(Project)方法加入到查询条件中去。    使用 Criteria 进行查询,主要要清晰的是 Hibernate 提供了那些类和方法来满足开发中查询条件的创建和组装,下面介绍几种用法:

1. 创建一个Criteria 实例 org.hibernate.Criteria接口表示特定持久类的一个查询。Session是Criteria实例的工厂。

Criteria crit = sess.createCriteria(Cat.class);

crit.setMaxResults(50);

List cats = crit.list();  

2. 限制结果集内容一个单独的查询条件是org.hibernate.criterion.Criterion 接口的一个实例。org.hibernate.criterion.Restrictions类定义了获得某些内置Criterion类型的工厂方法。

List cats = sess.createCriteria(Cat.class) .add(Restrictions.like("name", "Fritz%") )

.add( Restrictions.between("weight", minWeight, maxWeight) ).list();

约束可以按逻辑分组。  

List cats = sess.createCriteria(Cat.class) .add(Restrictions.like("name", "Fritz%") )

.add( Restrictions.or( Restrictions.eq( "age", new Integer(0) ),Restrictions.isNull("age")    ) ) .list();  

List cats = sess.createCriteria(Cat.class)

.add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk"} ) )

.add( Restrictions.disjunction() .add( Restrictions.isNull("age"))

.add( Restrictions.eq("age", new Integer(0) ) )

.add( Restrictions.eq("age", new Integer(1) ))        

.add( Restrictions.eq("age", new Integer(2) ) ) ))    

.list();  

Hibernate提供了相当多的内置criterion类型(Restrictions 子类), 但是尤其有用的是可以允许你直接使用SQL。  

List cats = sess.createCriteria(Cat.class)

.add( Restrictions.sql("lower({alias}.name) like lower(?)","Fritz%", Hibernate.STRING) ) .list();  

{alias}占位符应当被替换为被查询实体的列别名。Property实例是获得一个条件的另外一种途径。你可以通过调用Property.forName() 创建一个Property。    Property age = Property.forName("age");

List cats =sess.createCriteria(Cat.class)    

.add(Restrictions.disjunction()        

.add( age.isNull())        

.add( age.eq( new Integer(0) ))        

.add( age.eq( new Integer(1) ))        

.add( age.eq( new Integer(2) ))    ))    

.add( Property.forName("name").in( new String[] { "Fritz", "Izi","Pk" } ))    

.list();  

3.结果集排序你可以使用org.hibernate.criterion.Order来为查询结果排序。 

 List cats =sess.createCriteria(Cat.class)    

.add( Restrictions.like("name","F%")    

.addOrder( Order.asc("name"))    

.addOrder( Order.desc("age"))    

.setMaxResults(50)    

.list(); 

 List cats =sess.createCriteria(Cat.class)    

.add( Property.forName("name").like("F%"))    

.addOrder( Property.forName("name").asc())    

.addOrder( Property.forName("age").desc())    

.setMaxResults(50)    

.list();  

4. 关联你可以使用createCriteria()非常容易的在互相关联的实体间建立约束。  

List cats =sess.createCriteria(Cat.class)    

.add( Restrictions.like("name","F%")    

.createCriteria("kittens")        

.add( Restrictions.like("name","F%")    

.list();

注意第二个 createCriteria()返回一个新的 Criteria实例,该实例引用kittens 集合中的元素。接下来,替换形态在某些情况下也是很有用的。  

List cats =sess.createCriteria(Cat.class)   

 .createAlias("kittens","kt")    

.createAlias("mate","mt")    

.add( Restrictions.eqProperty("kt.name", "mt.name"))    

.list();

 (createAlias()并不创建一个新的 Criteria实例。)Cat实例所保存的之前两次查询所返回的kittens集合是 没有被条件预过滤的。如果你希望只获得 符合条件的kittens,你必须使用returnMaps()。  

List cats =sess.createCriteria(Cat.class)    

.createCriteria("kittens","kt")    

.add( Restrictions.eq("name", "F%"))    

.returnMaps()    

.list();

Iterator iter = cats.iterator(); while ( iter.hasNext() ) {

    Map map = (Map) iter.next();

    Cat cat =(Cat) map.get(Criteria.ROOT_ALIAS);

    Cat kitten = (Cat) map.get("kt");

}

5.动态关联抓取你可以使用setFetchMode()在运行时定义动态关联抓取的语义。  List cats =sess.createCriteria(Cat.class)    

.add( Restrictions.like("name", "Fritz%"))    

.setFetchMode("mate",FetchMode.EAGER)    

.setFetchMode("kittens",FetchMode.EAGER)    

.list();  

这个查询可以通过外连接抓取mate和kittens。  

6. 查询示例 org.hibernate.criterion.Example类允许你通过一个给定实例构建一个条件查询。  

Cat cat = new Cat();

cat.setSex(&apos;F&apos;);

cat.setColor(Color.BLACK);

List results =session.createCriteria(Cat.class)    

.add( Example.create(cat))    

.list();

版本属性、标识符和关联被忽略。默认情况下值为null的属性将被排除。可以自行调整Example使之更实用。 

 Example example =Example.create(cat)    

.excludeZeroes()          //exclude zero valuedproperties    

.excludeProperty("color")  //exclude the propertynamed"color"    

.ignoreCase()             //perform case insensitive stringcomparisons    

.enableLike();            //use like for string comparisons

List results =session.createCriteria(Cat.class)    

.add(example)    

.list();

甚至可以使用examples在关联对象上放置条件。  

List results =session.createCriteria(Cat.class)    

.add( Example.create(cat))    .createCriteria("mate")        

.add( Example.create( cat.getMate() ))   

 .list();

7. 投影(Projections)、聚合(aggregation)和分组(grouping)org.hibernate.criterion.Projections是 Projection 的实例工厂。我们通过调用setProjection()应用投影到一个查询。  

List results =session.createCriteria(Cat.class)    

.setProjection( Projections.rowCount())   

.add( Restrictions.eq("color", Color.BLACK))    

.list();  

List results =session.createCriteria(Cat.class)    

.setProjection(Projections.projectionList()        

.add( Projections.rowCount())        

.add( Projections.avg("weight"))        

.add( Projections.max("weight"))        

.add( Projections.groupProperty("color"))      

.list(); 

在一个条件查询中没有必要显式的使用 "group by" 。某些投影类型就是被定义为 分组投影,他 们也出现在SQL的groupby子句中。 可以选择把一个别名指派给一个投影,这样可以使投影值被约束或排序所引用。下面是两种不同的实现方式:   List results =session.createCriteria(Cat.class)    

.setProjection( Projections.alias(Projections.groupProperty("color"), "colr" ))    .addOrder( Order.asc("colr"))    

.list();



List results =session.createCriteria(Cat.class)    

.setProjection( Projections.groupProperty("color").as("colr"))    

.addOrder( Order.asc("colr"))    

.list();  

alias()和as()方法简便的将一个投影实例包装到另外一个 别名的Projection实例中。简而言之,当你添加一个投影到一个投影列表中时 你可以为它指定一个别名:  List results =session.createCriteria(Cat.class)    

.setProjection(Projections.projectionList()        

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

.add( Projections.avg("weight"), "avgWeight")        

.add( Projections.max("weight"), "maxWeight")        

.add( Projections.groupProperty("color"), "color")       

.addOrder( Order.desc("catCountByColor"))    

.addOrder( Order.desc("avgWeight"))    

.list();

 List results =session.createCriteria(Domestic.class,"cat")    

.createAlias("kittens","kit")    

.setProjection(Projections.projectionList()        

.add( Projections.property("cat.name"), "catName")        

.add( Projections.property("kit.name"), "kitName")       

.addOrder( Order.asc("catName"))    

.addOrder( Order.asc("kitName"))    

.list();

也可以使用Property.forName()来表示投影:  

List results =session.createCriteria(Cat.class)    

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

.add( Property.forName("color").eq(Color.BLACK))    

.list();

 List results =session.createCriteria(Cat.class)    

.setProjection(Projections.projectionList()        

.add( Projections.rowCount().as("catCountByColor"))       

.add( Property.forName("weight").avg().as("avgWeight"))       

.add( Property.forName("weight").max().as("maxWeight"))       

.add( Property.forName("color").group().as("color")       

.addOrder( Order.desc("catCountByColor"))    

.addOrder( Order.desc("avgWeight"))   

.list();

 8. 离线(detached)查询和子查询DetachedCriteria类使你在一个session范围之外创建一个查询,并且可以使用任意的 Session来执行它。  

DetachedCriteria query =DetachedCriteria.forClass(Cat.class)    

.add(Property.forName("sex").eq(&apos;F&apos;));

//创建一个Session

Session session = .;

Transaction txn = session.beginTransaction();

List results =query.getExecutableCriteria(session).setMaxResults(100).list();

txn.commit();

session.close();

DetachedCriteria也可以用以表示子查询。条件实例包含子查询可以通过 Subqueries或者Property获得。  

DetachedCriteria avgWeight =DetachedCriteria.forClass(Cat.class)    

.setProjection( Property.forName("weight").avg() );

session.createCriteria(Cat.class)    

.add( Property.forName("weight).gt(avgWeight))    

    .list();

 DetachedCriteria weights =DetachedCriteria.forClass(Cat.class)    

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

session.createCriteria(Cat.class)    

    .add(Subqueries.geAll("weight", weights))   

    .list();

相互关联的子查询也是有可能的:  

DetachedCriteria avgWeightForSex =DetachedCriteria.forClass(Cat.class,"cat2")    .setProjection( Property.forName("weight").avg() )

    .add(Property.forName("cat2.sex").eqProperty("cat.sex") );

session.createCriteria(Cat.class, "cat")

    .add( Property.forName("weight).gt(avgWeightForSex) )

    .list();

 

Hibernate3 提供了一种创新的方式来处理具有“显性(visibility)”规则的数据,那就是使用Hibernatefilter。 Hibernatefilter是全局有效的、具有名字、可以带参数的过滤器, 对于某个特定的Hibernatesession您可以选择是否启用(或禁用)某个过滤器。

17.1.  Hibernate过滤器(filters)

Hibernate3新增了对某个类或者集合使用预先定义的过滤器条件(filter criteria)的功能。过滤器条件相当于定义一个非常类似于类和各种集合上的“where”属性的约束子句,但是过滤器条件可以带参数。应用程序可以在运行时决定是否启用给定的过滤器,以及使用什么样的参数值。过滤器的用法很像数据库视图,只不过是在应用程序中确定使用什么样的参数的。

要使用过滤器,必须首先在相应的映射节点中定义。而定义一个过滤器,要用到位于<hibernate-mapping/>节点之内的<filter-def/>节点:

<filter-def name="myFilter"><filter-param name="myFilterParam"type="string"/></filter-def>

定义好之后,就可以在某个类中使用这个过滤器:

<class name="myClass" ...> ...<filter name="myFilter" condition=":myFilterParam =MY_FILTERED_COLUMN"/></class>

也可以在某个集合使用它:

<set ...> <filtername="myFilter" condition=":myFilterParam =MY_FILTERED_COLUMN"/></set>

可以在多个类或集合中使用某个过滤器;某个类或者集合中也可以使用多个过滤器。

Session对象中会用到的方法有:enableFilter(String filterName),getEnabledFilter(String filterName), 和 disableFilter(StringfilterName). Session中默认是启用过滤器的,必须通过Session.enabledFilter()方法显式的启用。该方法返回被启用的Filter的实例。以上文定义的过滤器为例:

session.enableFilter("myFilter").setParameter("myFilterParam","some-value");

注意,org.hibernate.Filter的方法允许链式方法调用。(类似上面例子中启用Filter之后设定Filter参数这个“方法链”)Hibernate的其他部分也大多有这个特性。

下面是一个比较完整的例子,使用了记录生效日期模式过滤有时效的数据:

<filter-def name="effectiveDate"><filter-param name="asOfDate"type="date"/></filter-def> <classname="Employee" ...> ... <many-to-onename="department" column="dept_id"class="Department"/> <propertyname="effectiveStartDate" type="date"column="eff_start_dt"/> <propertyname="effectiveEndDate" type="date"column="eff_end_dt"/> ... <!-- Notethat this assumes non-terminal records have an eff_end_dt set to amax db date for simplicity-sake注意,为了简单起见,此处假设雇用关系生效期尚未结束的记录的eff_end_dt字段的值等于数据库最大的日期--> <filter name="effectiveDate"condition=":asOfDate BETWEEN eff_start_dt andeff_end_dt"/> </class><class name="Department" ...> ...<set name="employees" lazy="true"><key column="dept_id"/><one-to-many class="Employee"/><filter name="effectiveDate" condition=":asOfDateBETWEEN eff_start_dt and eff_end_dt"/></set></class>

定义好后,如果想要保证取回的都是目前处于生效期的记录,只需在获取雇员数据的操作之前先开启过滤器即可:

Session session = ...;session.enabledFilter("effectiveDate").setParameter("asOfDate", newDate()); List results = session.createQuery("from Employee as ewhere e.salary > :targetSalary").setLong("targetSalary", new Long(1000000)) .list();

在上面的HQL中,虽然我们仅仅显式的使用了一个薪水条件,但因为启用了过滤器,查询将仅返回那些目前雇用关系处于生效期的,并且薪水高于一百万美刀的雇员的数据。

注意:如果你打算在使用外连接(或者通过HQL或load fetching)的同时使用过滤器,要注意条件表达式的方向(左还是右)。最安全的方式是使用左外连接(left outer joining)。并且通常来说,先写参数,然后是操作符,最后写数据库字段名。

在Filter定义之后,它可能被附加到多个实体和/或集合类,每个都有自己的条件。假若这些条件都是一样的,每次都要定义就显得很繁琐。因此,<filter-def/>被用来定义一个默认条件,它可能作为属性或者CDATA出现:

<filter-def name="myFilter" condition="abc>xyz">...</filter-def><filter-defname="myOtherFilter">abc=xyz</filter-def>当这个filter被附加到任何目的地,而又没有指明条件时,这个条件就会被使用。注意,换句话说,你可以通过给filter附加特别的条件来重载默认条件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值