工程和上一个一样,Topic有所改变,加了一个Topic的Msg的List列表属性,这个属性用来存放每个Topic下有多少条回帖。

例子项目:BBS小项目
(EJBQL是HQL的子集,所以直接说是HQL也无可厚非)
Category(版块):里面有不同的主题,不同的主题有不同的发帖
Topic(主题),Msg(具体的回复帖子)

Category与Topic之间的关系是一对多(OneToMany),Topic与Msg的关系也是一对多。(OneToMany)。

具体的类:
Category.java:

package com.bjsxt.hibernate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Category {
	private int id;
	private String name;
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}



Topic.java:


package com.bjsxt.hibernate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;


@Entity
@NamedQueries({
@NamedQuery(name="topic.selectCertainTopic", query="from Topic t where t.id = :id")})


public class Topic {
	private int id;
	private String title;
	private Category category;
	private Date createDate;
	private List<Msg> msgs = new ArrayList<Msg>();
	@OneToMany(mappedBy="topic")
	public List<Msg> getMsgs() {
		
		return msgs;
	}
	public void setMsgs(List<Msg> msgs) {
		this.msgs = msgs;
	}
	@Temporal(TemporalType.TIME)
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	@ManyToOne(fetch=FetchType.LAZY)
	public Category getCategory() {
		return category;
	}
	public void setCategory(Category category) {
		this.category = category;
	}
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	
}



Msg.java:


package com.bjsxt.hibernate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;


@Entity
public class Msg {
	private int id;
	private String cont;
	private Topic topic;
	@ManyToOne
	public Topic getTopic() {
		return topic;
	}
	public void setTopic(Topic topic) {
		this.topic = topic;
	}
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getCont() {
		return cont;
	}
	public void setCont(String cont) {
		this.cont = cont;
	}
	
}



MsgInfo.java:


package com.bjsxt.hibernate;

public class MsgInfo { //VO DTO Value Object username p1 p2 UserInfo->User->DB
	private int id;
	private String cont;
	private String topicName;
	private String categoryName;
	public MsgInfo(int id, String cont, String topicName, String categoryName) {
		super();
		this.id = id;
		this.cont = cont;
		this.topicName = topicName;
		this.categoryName = categoryName;
	}
	public String getTopicName() {
		return topicName;
	}
	public void setTopicName(String topicName) {
		this.topicName = topicName;
	}
	public String getCategoryName() {
		return categoryName;
	}
	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getCont() {
		return cont;
	}
	public void setCont(String cont) {
		this.cont = cont;
	}
	
}




各种测试:


//is empty and is not empty
	@Test
	public void testHQL_20() {
		Session session = sf.openSession();
		session.beginTransaction();
		//说t的Mags集合是否为空,即是寻找没有任何回帖的主题
		Query q = session.createQuery("from Topic t where t.msgs is empty");
		
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getId() + "-" + t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}


测试结果:


找到了没有任何回帖的主题(想得到msgs就得加一个一对多的导航)

Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         not (exists (select   //用了exists

             msgs1_.id 

         from

             Msg msgs1_ 

         where

             topic0_.id=msgs1_.topic_id))

 2-t1

 3-t2

 4-t3

 5-t4

 6-t5

 7-t6

 8-t7

 9-t8

 10-t9


is Null是测试一个属性空不空,is empty是测试一个集合空不空


——————————————————————————————————————


@Test
	public void testHQL_21() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("from Topic t where t.title like '%5'");
		
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getId() + "-" + t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         topic0_.title like '%5'


6-t5




其中,‘%’代表0个或多个,‘_’代表一个


——————————————————————————————————————


//不重要(使用HQL语句里面的一些函数)
	@Test
	public void testHQL_23() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("select lower(t.title)," +
					 "upper(t.title)," +
					 "trim(t.title)," +
					 "concat(t.title, '***')," +
					 "length(t.title)" +
					 " from Topic t ");
		
		for(Object o : q.list()) {
			Object[] arr = (Object[])o;
			System.out.println(arr[0] + "-" + arr[1] + "-" + arr[2] + "-" + arr[3] + "-" + arr[4] + "-");
		}
		session.getTransaction().commit();
		session.close();
		
	}


测试结果:


Hibernate: 

     select

         lower(topic0_.title) as col_0_0_,

         upper(topic0_.title) as col_1_0_,

         trim(topic0_.title) as col_2_0_,

         concat(topic0_.title,

         '***') as col_3_0_,

         length(topic0_.title) as col_4_0_ 

     from

         Topic topic0_

 t0-T0-t0-t0***-2-

 t1-T1-t1-t1***-2-

 t2-T2-t2-t2***-2-

 t3-T3-t3-t3***-2-

 t4-T4-t4-t4***-2-

 t5-T5-t5-t5***-2-

 t6-T6-t6-t6***-2-

 t7-T7-t7-t7***-2-

 t8-T8-t8-t8***-2-

 t9-T9-t9-t9***-2-


函数测试2:


@Test
	public void testHQL_24() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("select abs(t.id)," +
											 "sqrt(t.id)," +
											 "mod(t.id, 2)" +
											 " from Topic t ");
		
		for(Object o : q.list()) {
			Object[] arr = (Object[])o;
			System.out.println(arr[0] + "-" + arr[1] + "-" + arr[2] );
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


Hibernate: 

     select

         abs(topic0_.id) as col_0_0_,

         sqrt(topic0_.id) as col_1_0_,

         mod(topic0_.id,

         2) as col_2_0_ 

     from

         Topic topic0_

 1-1.0-1

 2-1.4142135623730951-0

 3-1.7320508075688772-1

 4-2.0-0

 5-2.23606797749979-1

 6-2.449489742783178-0

 7-2.6457513110645907-1

 8-2.8284271247461903-0

 9-3.0-1

 10-3.1622776601683795-0


——————————————————————————————————————


数据库的一些关键词


@Test
	public void testHQL_25() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("select current_date, current_time, current_timestamp, t.id from Topic t");
		
		for(Object o : q.list()) {
			Object[] arr = (Object[])o;
			System.out.println(arr[0] + " | " + arr[1] + " | " + arr[2] + " | " + arr[3]);
		}
		session.getTransaction().commit();
		session.close();
		
	}



current_date指的是数据库当前日期,current_time指的是数据库当前时间, current_timestamp指的是数据库当前日期和时间。 


测试结果:



Hibernate: 

     select

         current_date as col_0_0_,

         current_time as col_1_0_,

         current_timestamp as col_2_0_,

         topic0_.id as col_3_0_ 

     from

         Topic topic0_

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 1

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 2

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 3

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 4

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 5

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 6

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 7

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 8

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 9

 2015-02-01 | 15:59:53 | 2015-02-01 15:59:53.0 | 10

什么时候用到获取数据库的时间呢?


我直接取我程序里面的时间不就可以了吗?干嘛非要取数据库的时间呢?


因为在一个集群化的环境中,会有多台服务器围绕一个数据库来进行服务,如果你的日期需要在多台服务器上保持一致的话,你用服务器的时间能保持一致吗?肯定会有误差,但是我都用唯一的一台数据库的时间就不会有误差了。


——————————————————————————————————————


关于日期的比较:


@Test
	public void testHQL_26() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("from Topic t where t.createDate < :date");
		q.setParameter("date", new Date());
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         topic0_.createDate<?

 t0

 t1

 t2

 t3

 t4

 t5

 t6

 t7

 t8

 t9


——————————————————————————————————————


//group by语句用于结合合计函数,根据一个或多个列对结果集进行分组
	//你的group by后面的属性一定要在前面的select里面。
	@Test
	public void testHQL_27() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("select t.title, count(*) from Topic t group by t.title") ;
		for(Object o : q.list()) {
			Object[] arr = (Object[])o;
			System.out.println(arr[0] + "|" + arr[1]);
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果Hibernate: 


 

测试二:

select

         topic0_.title as col_0_0_,

         count(*) as col_1_0_ 

     from

         Topic topic0_ 

     group by

         topic0_.title

 t0|1

 t1|1

 t2|1

 t3|1

 t4|1

 t5|1

 t6|1

 t7|1

 t8|1

 t9|1:



@Test
	public void testHQL_28() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("select t.title, count(*) from Topic t group by t.title having count(*) >= 1") ;
		for(Object o : q.list()) {
			Object[] arr = (Object[])o;
			System.out.println(arr[0] + "|" + arr[1]);
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


——————————————————————————————————————

Hibernate: 

     select

         topic0_.title as col_0_0_,

         count(*) as col_1_0_ 

     from

         Topic topic0_ 

     group by

         topic0_.title 

     having

         count(*)>=1

 t0|1

 t1|1

 t2|1

 t3|1

 t4|1

 t5|1

 t6|1

 t7|1

 t8|1

 t9|1


@Test
	public void testHQL_29() {
		Session session = sf.openSession();
		session.beginTransaction();
		//取平均值,看哪些数据小于这些平均值
		Query q = session.createQuery("from Topic t where t.id < (select avg(t.id) from Topic t)") ;
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


一共10个id,(1+2+3+4+5+6+7+8+9+10)/10=5.5,所以取出的是小于5的id的title。

Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         topic0_.id<(

             select

                 avg(topic1_.id) 

             from

                 Topic topic1_

         )

 t0

 t1

 t2

 t3

 t4


——————————————————————————————————————


//ALL函数,就是满足ALL后条件内的所有值(其实找极端值就可以了呗)
	@Test
	public void testHQL_30() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("from Topic t where t.id < ALL (select t.id from Topic t where mod(t.id, 2)= 0) ") ;
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


——————————————————————————————————————

Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         topic0_.id<all (

             select

                 topic1_.id 

             from

                 Topic topic1_ 

             where

                 mod(topic1_.id, 2)=0

         )

 t0


//用in 可以实现exists的功能
	//但是exists执行效率高
	@Test
	public void testHQL_31() {
		Session session = sf.openSession();
		session.beginTransaction();// t.id not in (1)
		//括号里的意思是msg表里面存在不存在属于某个topic的msg(总的意思是找哪个topic下面没有回帖)
		Query q = session.createQuery("from Topic t where not exists (select m.id from Msg m where m.topic.id=t.id)") ;
//		Query q = session.createQuery("from Topic t where exists (select m.id from Msg m where m.topic.id=t.id)") ;
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


——————————————————————————————————————

Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         not (exists (select

             msg1_.id 

         from

             Msg msg1_ 

         where

             msg1_.topic_id=topic0_.id))

 t1

 t2

 t3

 t4

 t5

 t6

 t7

 t8

 t9


//update and delete
	//规范并没有说明是不是要更新persistent object,所以如果要使用,建议在单独的trasaction中执行
	@Test
	public void testHQL_32() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.createQuery("update Topic t set t.title = upper(t.title)") ;
		
		q.executeUpdate();
		q = session.createQuery("from Topic");
		for(Object o : q.list()) {
			Topic t = (Topic)o;
			System.out.println(t.getTitle());
		}
		session.createQuery("update Topic t set t.title = lower(t.title)")
			.executeUpdate();
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:


——————————————————————————————————————

Hibernate: 

     update

         Topic 

     set

         title=upper(title)

 Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_

 T0

 T1

 T2

 T3

 T4

 T5

 T6

 T7

 T8

 T9

 Hibernate: 

     update

         Topic 

     set

         title=lower(title)


//不重要
getNamedQuery方法拿到命名查询,这个命名查询写在实体类的上面
测试方法:
	@Test
	public void testHQL_33() {
		Session session = sf.openSession();
		session.beginTransaction();
		Query q = session.getNamedQuery("topic.selectCertainTopic");
		q.setParameter("id", 5);
		Topic t = (Topic)q.uniqueResult();
		System.out.println(t.getTitle());
		session.getTransaction().commit();
		session.close();
		
	}

实体类部分代码:


package com.bjsxt.hibernate;

import java.util.ArrayList;

@Entity
@NamedQueries({
@NamedQuery(name="topic.selectCertainTopic", query="from Topic t where t.id = :id")})
public class Topic {........


测试结果:


Hibernate: 

     select

         topic0_.id as id2_,

         topic0_.category_id as category4_2_,

         topic0_.createDate as createDate2_,

         topic0_.title as title2_ 

     from

         Topic topic0_ 

     where

         topic0_.id=?

 t4


——————————————————————————————————————


使用本地的SQL语句:


//Native(了解)
	@Test
	public void testHQL_34() {
		Session session = sf.openSession();
		session.beginTransaction();
		SQLQuery q = session.createSQLQuery("select * from category limit 2,4").addEntity(Category.class);
		List<Category> categories = (List<Category>)q.list();
		for(Category c : categories) {
			System.out.println(c.getName());
		}
		session.getTransaction().commit();
		session.close();
		
	}

测试结果:

Hibernate: 

     select

         * 

     from

         category limit 2,

         4

 c2

 c3

 c4

 c5


——————————————————————————————————————