`

Hibernate HQL, SQL查询及抓取策略

    博客分类:
  • ORM
 
阅读更多

1.Maven Dependency

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.fool.hibernate</groupId>
	<artifactId>hibernate_hql</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<hibernate-version>4.2.0.Final</hibernate-version>
		<junit-version>4.11</junit-version>
		<mysql-connector-version>5.1.24</mysql-connector-version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate-version}</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit-version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector-version}</version>
		</dependency>
	</dependencies>
</project>

 

 

2.Project Directory


 

3.src/main/resources

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
		<property name="connection.username">root</property>
		<property name="connection.password">123456</property>

		<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
		<property name="show_sql">true</property>
		<property name="format_sql">false</property>
		
		<property name="current_session_context_class">thread</property> 
		<property name="hbm2ddl.auto">update</property>

		<mapping class="org.fool.hibernate.model.Student" />
		<mapping class="org.fool.hibernate.model.Classroom" />
		<mapping class="org.fool.hibernate.model.Special" />
	</session-factory>
</hibernate-configuration>

 log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=warn, stdout

#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
#log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
#log4j.logger.org.hibernate.cache=debug

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

 

 

4.src/main/java

org.fool.hibernate.util

HibernateUtil.java

package org.fool.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil
{
	private static final SessionFactory sessionFactory;

	static
	{
		try
		{
			Configuration cfg = new Configuration().configure();
			ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
					.applySettings(cfg.getProperties()).buildServiceRegistry();

			sessionFactory = cfg.buildSessionFactory(serviceRegistry);
		}
		catch (Throwable e)
		{
			throw new ExceptionInInitializerError(e);
		}
	}

	private HibernateUtil()
	{
	}

	public static SessionFactory getSessionFactory()
	{
		return sessionFactory;
	}
}

org.fool.hibernate.model


Special.java

package org.fool.hibernate.model;

import java.util.Set;

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

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

@Entity
@Table(name = "t_special")
public class Special
{
	private int id;
	private String name;
	private String type;
	private Set<Classroom> classrooms;

	@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;
	}

	public String getType()
	{
		return type;
	}

	public void setType(String type)
	{
		this.type = type;
	}

	@OneToMany(mappedBy = "special")
	@LazyCollection(LazyCollectionOption.EXTRA)
	public Set<Classroom> getClassrooms()
	{
		return classrooms;
	}

	public void setClassrooms(Set<Classroom> classrooms)
	{
		this.classrooms = classrooms;
	}

	public Special()
	{
	}

	public Special(int id)
	{
		this.id = id;
	}

	public Special(String name, String type)
	{
		this.name = name;
		this.type = type;
	}

	@Override
	public String toString()
	{
		return "Special [id=" + id + ", name=" + name + ", type=" + type
				+ ", classrooms=" + classrooms + "]";
	}

}

 Classroom.java

package org.fool.hibernate.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

@Entity
@Table(name = "t_classroom")
@BatchSize(size = 20)
public class Classroom
{
	private int id;
	private String name;
	private int grade;
	private Set<Student> students;
	private Special special;

	@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;
	}

	public int getGrade()
	{
		return grade;
	}

	public void setGrade(int grade)
	{
		this.grade = grade;
	}

	@OneToMany(mappedBy = "classroom")
	@LazyCollection(LazyCollectionOption.EXTRA)
	@Fetch(FetchMode.SUBSELECT)
	public Set<Student> getStudents()
	{
		return students;
	}

	public void setStudents(Set<Student> students)
	{
		this.students = students;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "special_id")
	public Special getSpecial()
	{
		return special;
	}

	public void setSpecial(Special special)
	{
		this.special = special;
	}

	public Classroom()
	{

	}

	public Classroom(int id)
	{
		this.id = id;
	}

	public Classroom(String name, int grade, Special special)
	{
		this.name = name;
		this.grade = grade;
		this.special = special;
	}

	@Override
	public String toString()
	{
		return "Classroom [id=" + id + ", name=" + name + ", grade=" + grade
				+ ", students=" + students + ", special=" + special + "]";
	}

}

 Student.java

package org.fool.hibernate.model;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "t_student")
//@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Student
{
	private int id;
	private String name;
	private String sex;
	private Classroom classroom;

	@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;
	}

	public String getSex()
	{
		return sex;
	}

	public void setSex(String sex)
	{
		this.sex = sex;
	}

	// LAZY就是XML中的select,EAGER就表示XML中的join,默认为EAGER
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "classroom_id")
	public Classroom getClassroom()
	{
		return classroom;
	}

	public void setClassroom(Classroom classroom)
	{
		this.classroom = classroom;
	}

	public Student()
	{
	}

	public Student(String name, String sex, Classroom classroom)
	{
		this.name = name;
		this.sex = sex;
		this.classroom = classroom;
	}

	@Override
	public String toString()
	{
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex
				+ ", classroom=" + classroom + "]";
	}

}

 org.fool.hibernate.dto

StudentDTO.java

package org.fool.hibernate.dto;

/**
 * DTO对象没有存储的意义,仅仅是用来进行数据的传输的
 */
public class StudentDTO
{
	private int sid;
	private String sname;
	private String sex;
	private String cname;
	private String spename;

	public StudentDTO()
	{
	}

	public StudentDTO(int sid, String sname, String sex, String cname,
			String spename)
	{
		this.sid = sid;
		this.sname = sname;
		this.sex = sex;
		this.cname = cname;
		this.spename = spename;
	}

	public int getSid()
	{
		return sid;
	}

	public void setSid(int sid)
	{
		this.sid = sid;
	}

	public String getSname()
	{
		return sname;
	}

	public void setSname(String sname)
	{
		this.sname = sname;
	}

	public String getSex()
	{
		return sex;
	}

	public void setSex(String sex)
	{
		this.sex = sex;
	}

	public String getCname()
	{
		return cname;
	}

	public void setCname(String cname)
	{
		this.cname = cname;
	}

	public String getSpename()
	{
		return spename;
	}

	public void setSpename(String spename)
	{
		this.spename = spename;
	}

	@Override
	public String toString()
	{
		return "StudentDTO [sid=" + sid + ", sname=" + sname + ", sex=" + sex
				+ ", cname=" + cname + ", spename=" + spename + "]";
	}

}

 StuDto.java

package org.fool.hibernate.dto;

import org.fool.hibernate.model.Classroom;
import org.fool.hibernate.model.Special;
import org.fool.hibernate.model.Student;

public class StuDto
{
	private Student stu;
	private Classroom cla;
	private Special spe;

	public StuDto()
	{
	}

	public StuDto(Student stu, Classroom cla, Special spe)
	{
		this.stu = stu;
		this.cla = cla;
		this.spe = spe;
	}

	public Student getStu()
	{
		return stu;
	}

	public void setStu(Student stu)
	{
		this.stu = stu;
	}

	public Classroom getCla()
	{
		return cla;
	}

	public void setCla(Classroom cla)
	{
		this.cla = cla;
	}

	public Special getSpe()
	{
		return spe;
	}

	public void setSpe(Special spe)
	{
		this.spe = spe;
	}

}

 

 

5.src/test/java

先插入相关数据,便于进行测试

TestAdd.java

package org.fool.hibernate.test;

import java.util.Random;

import org.fool.hibernate.model.Classroom;
import org.fool.hibernate.model.Special;
import org.fool.hibernate.model.Student;
import org.fool.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.junit.Test;

public class TestAdd
{

	Random ran = new Random();

	@Test
	public void testAddSpecial()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		session.save(new Special("计算机教育", "教育类"));
		session.save(new Special("计算机应用技术", "高职类"));
		session.save(new Special("计算机网络技术", "高职类"));
		session.save(new Special("计算机信息管理", "高职类"));
		session.save(new Special("数学教育", "教育类"));
		session.save(new Special("物理教育", "教育类"));
		session.save(new Special("化学教育", "教育类"));
		session.save(new Special("会计", "高职类"));
		session.save(new Special("英语教育", "教育类"));

		session.getTransaction().commit();
	}

	@Test
	public void testAddClassroom()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		session.save(new Classroom("计算机教育1班", 2009, new Special(1)));
		session.save(new Classroom("计算机教育2班", 2009, new Special(1)));
		session.save(new Classroom("计算机教育班", 2010, new Special(1)));
		session.save(new Classroom("计算机教育班", 2011, new Special(1)));
		session.save(new Classroom("计算机应用技术", 2009, new Special(2)));
		session.save(new Classroom("计算机应用技术", 2010, new Special(2)));
		session.save(new Classroom("计算机应用技术", 2011, new Special(2)));
		session.save(new Classroom("计算机网络技术", 2009, new Special(3)));
		session.save(new Classroom("计算机网络技术", 2010, new Special(3)));
		session.save(new Classroom("计算机网络技术", 2011, new Special(3)));
		session.save(new Classroom("计算机信息管理", 2009, new Special(4)));
		session.save(new Classroom("计算机信息管理", 2010, new Special(4)));
		session.save(new Classroom("计算机信息管理", 2011, new Special(4)));
		session.save(new Classroom("数学教育1班", 2009, new Special(5)));
		session.save(new Classroom("数学教育2班", 2009, new Special(5)));
		session.save(new Classroom("数学教育3班", 2009, new Special(5)));
		session.save(new Classroom("数学教育1班", 2010, new Special(5)));
		session.save(new Classroom("数学教育2班", 2010, new Special(5)));
		session.save(new Classroom("数学教育1班", 2011, new Special(5)));
		session.save(new Classroom("数学教育2班", 2011, new Special(5)));
		session.save(new Classroom("物理教育", 2009, new Special(6)));
		session.save(new Classroom("物理教育", 2010, new Special(6)));
		session.save(new Classroom("物理教育", 2011, new Special(6)));
		session.save(new Special("化学教育", "教育类"));
		session.save(new Classroom("化学教育", 2009, new Special(7)));
		session.save(new Classroom("化学教育", 2010, new Special(7)));
		session.save(new Classroom("化学教育", 2011, new Special(7)));
		session.save(new Classroom("会计", 2009, new Special(8)));
		session.save(new Classroom("会计", 2010, new Special(8)));
		session.save(new Classroom("会计", 2011, new Special(8)));
		session.save(new Classroom("英语教育A班", 2009, new Special(9)));
		session.save(new Classroom("英语教育B班", 2009, new Special(9)));
		session.save(new Classroom("英语教育A班", 2010, new Special(9)));
		session.save(new Classroom("英语教育B班", 2010, new Special(9)));
		session.save(new Classroom("英语教育A班", 2011, new Special(9)));
		session.save(new Classroom("英语教育B班", 2011, new Special(9)));
		session.save(new Classroom("选修课班A", 2011, null));
		session.save(new Classroom("选修课班B", 2011, null));
		session.getTransaction().commit();

	}

	@Test
	public void testRan()
	{
		for (int i = 0; i < 20; i++)
		{
			System.out.println(ran.nextInt(2));
		}
	}

	@Test
	public void testAddStu()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String[] sexs = new String[] { "男", "女" };
		// 仅仅添加32个班 的学生,方便做外连接的实验
		for (int i = 1; i <= 32; i++)
		{
			// 每个班40个学生
			for (int j = 1; j <= 40; j++)
			{
				session.save(new Student(getName(), sexs[ran.nextInt(2)],
						new Classroom(i)));
			}
		}
		
		session.getTransaction().commit();

	}

	@Test
	public void testAddStuNull()
	{
		// 添加100个没有班级的学生方便做right连接查询
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String[] sexs = new String[] { "男", "女" };
		for (int j = 1; j <= 100; j++)
		{
			session.save(new Student(getName(), sexs[ran.nextInt(2)], null));
		}
		session.getTransaction().commit();

	}

	private String getName()
	{
		String[] name1 = new String[] { "孔", "张", "叶", "李", "叶入", "孔令", "张立",
				"陈", "刘", "牛", "夏侯", "令", "令狐", "赵", "母", "穆", "倪", "张毅", "称",
				"程", "王", "王志", "刘金", "冬", "吴", "马", "沈" };

		String[] name2 = new String[] { "凡", "课", "颖", "页", "源", "都", "浩", "皓",
				"西", "东", "北", "南", "冲", "昊", "力", "量", "妮", "敏", "捷", "杰",
				"坚", "名", "生", "华", "鸣", "蓝", "春", "虎", "刚", "诚" };

		String[] name3 = new String[] { "吞", "明", "敦", "刀", "备", "伟", "唯", "楚",
				"勇", "诠", "佺", "河", "正", "震", "点", "贝", "侠", "伟", "大", "凡",
				"琴", "青", "林", "星", "集", "财" };

		boolean two = ran.nextInt(50) >= 45 ? false : true;
		
		if (two)
		{
			String n1 = name1[ran.nextInt(name1.length)];
			String n2;
			int n = ran.nextInt(10);
			
			if (n > 5)
			{
				n2 = name2[ran.nextInt(name2.length)];
			}
			else
			{
				n2 = name3[ran.nextInt(name3.length)];
			}
			
			return n1 + n2;
		}
		else
		{
			String n1 = name1[ran.nextInt(name1.length)];
			String n2 = name2[ran.nextInt(name2.length)];
			String n3 = name3[ran.nextInt(name3.length)];
			
			return n1 + n2 + n3;
		}
	}
}

 HQL查询

TestHQL.java

package org.fool.hibernate.test;

import java.util.List;

import org.fool.hibernate.dto.StudentDTO;
import org.fool.hibernate.model.Special;
import org.fool.hibernate.model.Student;
import org.fool.hibernate.util.HibernateUtil;
import org.hibernate.Query;
import org.hibernate.Session;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestHQL
{

	@Test
	public void test01()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		Query query = session.createQuery("from Special");

		List<Special> specials = query.list();

		for (Special special : specials)
		{
			System.out.println(special.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test02()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 对于HQL而言,都是基于对象进行查询的
		 */
		// Query query =
		// session.createQuery("select * from Special");//不能使用select *进行查询
		/**
		 * 可以使用链式查询的方式
		 */
		List<Special> specials = session.createQuery(
				"select special from Special special").list();

		for (Special special : specials)
		{
			System.out.println(special.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test03()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		List<Student> students = session.createQuery(
				"from Student where name like '%张%'").list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test04()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 基于?的条件的查询,特别注意:jdbc设置参数的最小下标是1,hibernate是0
		 */
		List<Student> students = session
				.createQuery("from Student where name like ?")
				.setParameter(0, "%王%").list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test05()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 基于别名进行查询,使用:xxx来说明别名的名称
		 */
		String hql = "from Student where name like :name and sex = :sex";

		List<Student> students = session.createQuery(hql)
				.setParameter("name", "%牛%").setParameter("sex", "男").list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test06()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 使用uniqueResult可以返回唯一的一个值
		 */
		String hql = "select count(*) from Student where name like :name and sex = :sex";

		Long count = (Long) session.createQuery(hql)
				.setParameter("name", "%牛%").setParameter("sex", "男")
				.uniqueResult();

		System.out.println(count);

		session.getTransaction().commit();
	}

	@Test
	public void test07()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 使用uniqueResult可以返回唯一的一个值
		 */
		String hql = "select student from Student student where id = :id";

		Student student = (Student) session.createQuery(hql)
				.setParameter("id", 1).uniqueResult();

		System.out.println(student.getName());

		session.getTransaction().commit();
	}

	@Test
	public void test08()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 基于投影的查询,通过在列表中存储一个对象的数组
		 */
		String hql = "select stu.sex, count(*) from Student stu group by stu.sex";

		List<Object[]> objects = session.createQuery(hql).list();

		for (Object[] obj : objects)
		{
			System.out.println(obj[0] + ":" + obj[1]);
		}

		session.getTransaction().commit();
	}

	@Test
	public void test09()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 如果对象中相应的导航对象,可以直接导航完成查询
		 */
		String hql = "select stu from Student stu where stu.classroom.name = ? and stu.name like ?";

		List<Student> students = session.createQuery(hql)
				.setParameter(0, "计算机教育班").setParameter(1, "%张%").list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test10()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 可以使用in来设置基于列表的查询,此处的查询需要使用别名进行查询 特别注意,使用in的查询必须在其他的查询之后
		 */
		String hql = "select stu from Student stu where stu.name like ? and stu.classroom.id in(:id)";

		List<Student> students = session.createQuery(hql)
				.setParameter(0, "%张%")
				.setParameterList("id", new Integer[] { 1, 2 }).list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test11()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 使用setFirstResult和setMaxResults可以完成分页的offset和pageSize的设置
		 */
		String hql = "select stu from Student stu where stu.classroom.id in(:id)";

		List<Student> students = session.createQuery(hql)
				.setParameterList("id", new Integer[] { 1, 2 })
				.setFirstResult(0).setMaxResults(10).list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test12()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 可以通过is null来查询为空的对象,和sql一样不能使用=来查询null的对象
		 */
		String hql = "select stu from Student stu where stu.classroom is null";

		List<Student> students = session.createQuery(hql).setFirstResult(0)
				.setMaxResults(10).list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test13()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 使用对象的导航可以完成连接,但是是基于cross join,效率不高,可以直接使用join来完成连接
		 */
		String hql = "select stu from Student stu left join stu.classroom cla where cla.id = ?";

		List<Student> students = session.createQuery(hql).setParameter(0, 2)
				.setFirstResult(0).setMaxResults(10).list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test14()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String hql = "select cla.grade, cla.name, count(stu.classroom.id) from Student stu right join stu.classroom cla group by cla.id";

		List<Object[]> objects = session.createQuery(hql).list();

		for (Object[] obj : objects)
		{
			System.out.println(obj[0] + " , " + obj[1] + " , " + obj[2]);
		}

		session.getTransaction().commit();
	}

	@Test
	public void test15()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 直接可以使用new XXXObjectDTO完成查询,注意,一定要加上Object的完整包名
		 * 这里使用的newXXXObjectDTO,必须在对象中加入相应的构造函数
		 */
		String hql = new StringBuilder()
				.append("select new org.fool.hibernate.dto.StudentDTO")
				.append("(stu.id as sid, stu.name as sname, stu.sex as sex, cla.name as cname, spe.name as spename) ")
				.append("from Student stu left join stu.classroom cla left join cla.special spe")
				.toString();

		List<StudentDTO> students = session.createQuery(hql).list();

		for (StudentDTO student : students)
		{
			System.out.println(student);
		}

		session.getTransaction().commit();
	}

	@Test
	public void test16()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * having是为group来设置条件的
		 */
		String hql = new StringBuilder()
				.append("select spe.name, count(stu.classroom.special.id) ")
				.append("from Student stu right join stu.classroom.special spe ")
				.append("group by spe.name having count(stu.classroom.special.id) > 150")
				.toString();

		List<Object[]> objects = session.createQuery(hql).list();

		for (Object[] obj : objects)
		{
			System.out.println(obj[0] + " , " + obj[1]);
		}

		session.getTransaction().commit();
	}

	@Test
	public void test17()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String hql = new StringBuilder()
				.append("select stu.sex, spe.name, count(stu.classroom.special.id) ")
				.append("from Student stu right join stu.classroom.special spe ")
				.append("group by stu.sex, spe.name").toString();

		List<Object[]> objects = session.createQuery(hql).list();

		for (Object[] obj : objects)
		{
			System.out.println(obj[0] + " , " + obj[1] + ", " + obj[2]);
		}

		session.getTransaction().commit();
	}
}

 SQL查询

TestSQL.java

package org.fool.hibernate.test;

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

import org.fool.hibernate.dto.StuDto;
import org.fool.hibernate.dto.StudentDTO;
import org.fool.hibernate.model.Classroom;
import org.fool.hibernate.model.Special;
import org.fool.hibernate.model.Student;
import org.fool.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestSQL
{

	@Test
	public void test01()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String sql = "select * from t_student where name like ?";

		List<Student> students = session.createSQLQuery(sql)
				.addEntity(Student.class).setParameter(0, "%牛%")
				.setFirstResult(0).setMaxResults(10).list();

		for (Student student : students)
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test02()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String sql = new StringBuilder()
				.append("select {stu.*}, {cla.*}, {spe.*} ")
				.append("from t_student stu left join t_classroom cla on(stu.classroom_id=cla.id) ")
				.append("left join t_special spe on(cla.special_id=spe.id) ")
				.append("where stu.name like ?").toString();

		List<Object[]> students = session.createSQLQuery(sql)
				.addEntity("stu", Student.class)
				.addEntity("cla", Classroom.class)
				.addEntity("spe", Special.class).setParameter(0, "%牛%")
				.setFirstResult(0).setMaxResults(10).list();

		Student stu = null;
		Classroom cla = null;
		Special spe = null;
		List<StuDto> list = new ArrayList<StuDto>();

		for (Object[] obj : students)
		{
			stu = (Student) obj[0];
			cla = (Classroom) obj[1];
			spe = (Special) obj[2];
			System.out.println(stu.getName() + ", " + cla.getName() + ", "
					+ spe.getName());
			
			list.add(new StuDto(stu, cla, spe));
		}

		session.getTransaction().commit();
	}

	@Test
	public void test03()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		String sql = new StringBuilder()
				.append("select stu.id as sid, stu.name as sname, stu.sex as sex, cla.name as cname, spe.name as spename ")
				.append("from t_student stu left join t_classroom cla on(stu.classroom_id=cla.id) ")
				.append("left join t_special spe on(cla.special_id=spe.id) ")
				.append("where stu.name like ?").toString();

		List<StudentDTO> students = session
				.createSQLQuery(sql)
				.setResultTransformer(
						Transformers.aliasToBean(StudentDTO.class))
				.setParameter(0, "%牛%").setFirstResult(0).setMaxResults(10)
				.list();

		for (StudentDTO studentDTO : students)
		{
			System.out.println(studentDTO);
		}

		session.getTransaction().commit();
	}
}

 抓取策略

TestFetch.java

package org.fool.hibernate.test;

import java.util.List;

import org.fool.hibernate.model.Classroom;
import org.fool.hibernate.model.Student;
import org.fool.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestFetch
{
	@Test
	public void test01()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/*
		 * 对于Annotation的配置而言,默认就是基于join的抓取的,所以只会发出一条SQL
		 */
		Student student = (Student) session.load(Student.class, 1);

		System.out.println(student.getName() + ", "
				+ student.getClassroom().getName() + ", "
				+ student.getClassroom().getSpecial().getName());

		session.getTransaction().commit();
	}

	@Test
	public void test02()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 由于基于Annotation的配置没有延迟加载,此时会把所有的关联对象查询上来,发大量的SQL语句
		 */
		List<Student> students = session.createQuery("from Student").list();

		for (Student student : students)
		{
			System.out.println(student.getName() + ", "
					+ student.getClassroom().getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test03()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 在XML中配置了fetch=join仅仅只是对load的对象有用,对HQL中查询的对象无用,
		 * 所以此时会发出查询班级的SQL,解决的这个SQL的问题有两种方案,
		 * 
		 * 一种是设置对象的抓取的batch-size
		 * 
		 * 另一种方案在HQL中使用fetch来指定抓取
		 */
		List<Student> students = session.createQuery("from Student").list();

		for (Student student : students)
		{
			System.out.println(student.getName() + ", "
					+ student.getClassroom().getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test04()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		/**
		 * 在XML中配置了fetch=join仅仅只是对load的对象有用,对HQL中查询的对象无用,
		 * 所以此时会发出查询班级的SQL,解决的这个SQL的问题有两种方案,
		 * 
		 * 一种是设置对象的抓取的batch-size
		 * 
		 * 另一种方案在HQL中使用fetch来指定抓取 特别注意,如果使用了join fetch就无法使用count(*)
		 * 
		 * 基于Annotation由于默认的many-to-one的抓取策略是EAGER的,所以当抓取classroom时会自动
		 * 发出多条SQL去查询相应的special,此时可以通过join fetch继续完成对关联的抓取,
		 * 获取直接将关联对象的fecth设置为LAZY,但是使用LAZY所带来的问题是在查询关联对象时 需要发出相应的SQL,很多时候也会影响效率
		 */
		String hql = "select stu from Student stu join fetch stu.classroom";

		List<Student> students = session.createQuery(hql).list();

		for (Student student : students)
		{
			System.out.println(student.getName() + ", "
					+ student.getClassroom().getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test05()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		Classroom classroom = (Classroom) session.load(Classroom.class, 1);

		System.out.println(classroom.getName());

		/**
		 * 此时会在发出一条SQL取学生对象
		 */
		for (Student student : classroom.getStudents())
		{
			System.out.println(student.getName());
		}

		session.getTransaction().commit();
	}

	@Test
	public void test06()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		session.beginTransaction();

		List<Classroom> classrooms = session.createQuery("from Classroom")
				.list();

		for (Classroom classroom : classrooms)
		{
			System.out.println(classroom.getName());

			/**
			 * 对于通过HQL取班级列表并且获取相应的学生列表时,fecth=join就无效了
			 * 第一种方案可以设置set的batch-size来完成批量的抓取
			 * 第二中方案可以设置fetch=subselect,使用subselect会完成根据查询出来的班级进行一次对学生对象的子查询
			 */
			for (Student student : classroom.getStudents())
			{
				System.out.println(student.getName());
			}
		}

		session.getTransaction().commit();
	}
}

 

 

6.Best in Practice

使用二级缓存的步骤

1、hibernate并没有提供相应的二级缓存的组件,所以需要加入额外的二级缓存包,常用的二级缓存包是ECHcache

...
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-ehcache</artifactId>
	<version>${hibernate-version}</version>
</dependency>
...

2、在hibernate.cfg.xml中配置开启二级缓存

...
<!-- 设置二级缓存为true -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 设置二级缓存所提供的类 -->
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>
<!-- 在hibernate4.0之后需要设置facotory_class -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
...

3、设置相应的ehcache.xml文件,在这个文件中配置二级缓存的参数,并且将文件在cfg文件中配置

...
<!-- 说明ehcache的配置文件路径 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
...

4、开启二级缓存

基于xml的配置中设置

...
<class name="Student" table="t_student">
    <cache usage="read-only"/>
	...
</class>
...

 基于Annotation的配置中设置

...
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
...

5、二级缓存缓存的是对象,它是把所有的对象缓存到内存中,一定注意是基于对象的缓存

6、查询缓存是针对HQL语句的缓存,查询缓存仅仅只会缓存id而不会缓存对象

...
<!--设置相应的查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
...

 

...
List<Student> ls = session.createQuery("from Student")
		.setCacheable(true)//开启查询缓存,查询缓存也是SessionFactory级别的缓存
		.setFirstResult(0).setMaxResults(50).list();
...

 

并发

一般并发会导致更新丢失,有两种解决方案可以解决并发的问题

1、悲观锁

悲观锁是Hibernate基于数据库的机制来实现的,hibernate是基于同步的机制实现的,当只要读取了这个对象,这个对象就会被加锁有在第一个对象读取完成之后第二个对象才能读取。这样将会大大的影响效率。

...
//只要使用这种方式来load就会为其增加锁
Student stu = (Student)session.load(Student.class,1,LockOptions.UPGRADE);
...

2、乐观锁

乐观锁是在数据库中增加一个version的字段来实现的,version在xml配置中要在所有property属性前面,每一次修改都会让这个字段的数字加1,在读取的时候根据version这个版本数据来读取,这样如果并发修改就会抛出异常

...
<hibernate-mapping package="org.fool.hibernate.model">
    <class name="Student" table="t_student">
    	<cache usage="read-only"/>
        <id name="id">
          	<generator class="native"/>
        </id>
        <version name="version"/>
        <property name="name"/>
        <property name="sex"/>
        <many-to-one name="classroom" column="classroom_id" fetch="select"/>
    </class>
</hibernate-mapping>

 

使用Hibernate的最佳实践

 1、在做关系尽可能使用单向关联,不要使用双向关联

 2、在大项目中(数据量如果超过百万条的项目,使用Hibernate可以酌情考虑以下几个原则)

 2.1、不要使用对象关联,尽可能用冗余字段来替代外键(使用冗余字段所带来的问题就是在修改时必须修改所有的冗余)

 2.2、查询数据不再使用HQL,全部使用SQL查询,如果涉及缓存,自己根据情况加入相应的缓存,而不是用Hibernate的缓存

 

  • 大小: 18.9 KB
  • 大小: 22.1 KB
分享到:
评论

相关推荐

    hibernate学习笔记

    Hibernate 学习笔记 Hibernate 学习笔记 1 第一个hibernate项目(hibernate_first) 2 测试实体对象的生命周期(hibernate_session) 3 ...hibernate抓取策略 53 Hibernate最佳实践(Best Practices) 55

    Hibernate3开发.pdf

    包括:使用Hibernate实现增删改查、HQL语句、条件查询、Native SQL、批量处理 第五章:关系映射 包括:集合映射、一对一、一对多、多对多 第六章:性能提升和二级缓存 包括:抓取策略、集合的性能、二级缓存、...

    Hibernate实战(第2版 中文高清版)

     13.2.2 通过子查询预抓取集合   13.2.3 通过联结即时抓取   13.2.4 给二级表优化抓取   13.2.5 优化指导方针   13.3 高速缓存基本原理   13.3.1 高速缓存策略和范围   13.3.2 Hibernate高速缓存架构 ...

    Hibernate+中文文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    hibernate3.2中文文档(chm格式)

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    HibernateAPI中文版.chm

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    Hibernate 中文 html 帮助文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 ...

    Hibernate中文详细学习文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    最全Hibernate 参考文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. select子句 14.5. 聚集函数 14.6. 多态查询 14.7. where子句 14.8. 表达式 14.9. order by子句 ...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    hibernate 体系结构与配置 参考文档(html)

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9....

    Hibernate教程

    15. HQL: Hibernate查询语言 15.1. 大小写敏感性问题 15.2. from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order by...

    hibernate 教程

    Hibernate查询语言(Query Language), 即HQL 11.1. 大小写敏感性(Case Sensitivity) 11.2. from 子句 11.3. 联合(Associations)和连接(joins) 11.4. select子句 11.5. 统计函数(Aggregate ...

    Hibernate3+中文参考文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. select子句 14.5. 聚集函数 14.6. 多态查询 14.7. where子句 14.8. 表达式 14.9. order by子句 ...

    hibernate3.04中文文档.chm

    15. HQL: Hibernate查询语言 15.1. 大小写敏感性问题 15.2. from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order by...

    Hibernate参考文档

    14. HQL: Hibernate查询语言 14.1. 大小写敏感性问题 14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 ...

    hibernate 框架详解

    15. HQL: Hibernate查询语言 15.1. 大小写敏感性问题 15.2. from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order ...

    hibernate

    Hibernate查询语言(Query Language), 即HQL 11.1. 大小写敏感性(Case Sensitivity) 11.2. from 子句 11.3. 联合(Associations)和连接(joins) 11.4. select子句 11.5. 统计函数(Aggregate ...

    hibernate总结

    2. 通过HQL/SQL 检索 hibernate query language (面向对象的查询语言) * a) 不再操纵表,它操纵的是持久化类的对象 b) 面向对象的 3. QBC ( query by criteria ) 更加面向对象 4. QBE ( query by Example ) 5....

    NHibernate参考文档 2.0.0 chm

    16.1.6. 使用子查询抓取(Using subselect fetching) 16.2. 二级缓存(The Second Level Cache) 16.2.1. 缓存映射(Cache mappings) 16.2.2. 策略:只读缓存(Strategy: read only) 16.2.3. 策略:读/写缓存...

Global site tag (gtag.js) - Google Analytics