`

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_HQL大全

    8. **Fetch策略**:HQL提供了不同的抓取策略,如immediate(立即加载)、delayed(延迟加载)等,用于控制何时加载关联对象或集合,以优化内存使用和查询性能。 #### 三、案例分析与应用技巧 假设我们需要查询所有...

    HIBERNATE HQL

    通过上述介绍,我们可以看到HQL的强大之处在于它能够有效地处理复杂的对象关系,同时也提供了一些高级功能,如延迟加载和抓取策略,帮助优化数据访问性能。理解和掌握HQL将极大地提升开发者在Hibernate项目中的效率...

    Hibernate HQL教程

    ### Hibernate HQL 教程知识点总结 #### 1.1 HQL基础 ##### 1.1.1 默认数据库表和数据 - **介绍**: 本文档以`joblog`数据库为例,该数据库包含三个表:`student`(学生表)、`course`(课程表)和`sc`(选课表)。 - **...

    Hibernate_day04.zip

    总的来说,Hibernate Day 04的学习涵盖了从基础查询到高级特性的广泛内容,包括HQL、Criteria API、抓取策略、缓存、事务和对象状态等。通过深入理解这些知识点,开发者能够更加高效地使用Hibernate进行数据库操作,...

    Hibernate优化方案

    通过调整HQL书写方式、查询方法和抓取策略,可以影响生成的SQL。例如,HQL和SQL的选择应基于数据库结构和数据需求。 2. 使用正确的查询方法: - `get()`和`load()`方法:`load()`使用二级缓存,而`get()`在一级...

    Hibernate5.2.11高清版,最新版本

    抓取策略(Fetching)介绍了Hibernate如何抓取对象及其关联对象,包括延迟加载和立即加载的策略选择。 批量操作(Batching)涉及如何执行数据库批处理操作,这对于执行大量数据更新或插入非常有用。 缓存机制...

    Hibernate ORM 5.3.7.Final User Guide

    11. 数据抓取(Fetching):手册解释了在Hibernate中抓取数据的不同策略及其适用场景。 12. 批处理(Batching):这部分提供了在Hibernate中如何有效执行批处理操作的信息。 13. 缓存(Caching):涵盖了Hibernate缓存...

    hibernate 框架的基础四

    ### Hibernate框架基础四:深入理解HQL多表检索...综上所述,通过深入了解HQL的多表检索技术、事务管理及隔离级别、查询优化方法以及合理的抓取策略配置,可以帮助开发者更高效地使用Hibernate框架处理复杂的业务逻辑。

    如何提高hibernate性能

    使用HQL(Hibernate Query Language)或Criteria API进行查询,它们可以更好地利用Hibernate的优化机制,减少与数据库的交互次数。 9. **避免N+1查询问题**: 在关联查询中,确保一次获取所需的所有关联数据,以...

    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....

    Hibernate关键知识点大全

    - Hibernate特有的面向对象的查询语言,类似于SQL,但更适应对象模型。 15. **QBC(Query By Criteria)和QBE(Query By Example)** - 这两种查询方式提供了基于对象和示例的查询接口,简化了复杂查询的编写。 ...

    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....

    java私塾独家首发最新Hibernate4教程

    - **查询语言**:支持HQL(Hibernate Query Language)和原生SQL查询。 **1.4 Hibernate4体系结构** Hibernate4的核心模块包括Session、SessionFactory、Transaction等。其中SessionFactory是创建Session的工厂,...

    Hibernate3开发.pdf

    Hibernate提供了抓取策略、集合性能优化、二级缓存、查询缓存和管理缓存等策略。通过这些策略,可以有效地减少数据库的访问次数,提高数据的存取速度。 最后,了解Hibernate的基本实现原理,如分增删改查的操作说明...

    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子句 ...

Global site tag (gtag.js) - Google Analytics