Hibernate注解开发

Hibernate开发步骤

1.导入Hibernate开发包中lib文件夹中required下的所有jar包
2.在src根目录建立hibernate主配置文件,hibernate.cfg.xml,cfg:configuration配置。
主配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--导入标签库:在Hibernate核心开发包中hibernate-configuration-3.0.dtd中-->
<!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:要配置的位置在:    
	    hibernate解压缩后的文件/project/etc/hibernate.properties -->
	<session-factory>
		<!-- 数据库连接参数 -->
		<!-- 使用property标签对SessionFactory属性进行配置 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!-- 连接本地mysql可以省略地址 -->
		<property name="hibernate.connection.url">jdbc:mysql:///servletdb</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">1234</property>
		<!--配置currentSession:当前线程对应session-->
		<propertyname="hibernate.current_session_context_class">thread</property>  
		<!-- hibernate自动生成sql,将sql展示出来 -->
		<property name="show_sql">true</property>
		<!-- 对sql格式化输出,将sql变美观 -->
		<property name="hibernate.format_sql">true</property>
		<!-- 配置hibernate方言:hibernate.dialect
		    因为Hibernate无需编写sql,但其底层需要把代码翻译成sql;方言也就是告知hibernate以何种sql语句进行翻译-->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 配置hibernate映射文件地址,映射文件是实体类和数据库表中对应的表的配置。 -->
		<mapping resource="entity/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

hibernate中的session相当于Connection,一个Session表示和数据库的一次会话。
Sessionfactory:创建session的一个工厂类,相当于DriverManager

3.编写实体类
4.编写实体映射文件:描述表和实体类之间的映射关系

一个表对应一个Java类,hbm:hibernate mapping
命名:类名.hbm.xml
位置:和实体类同包

<?xml version="1.0" encoding="UTF-8"?>
<!--导入标签库-->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!-- 配置User类和t_user之间的映射关系
		name:全限定名 -->
	<class name="entity.User" table="t_user">
		<!-- 配置字段名和属性名之间的映射关系
			先配置主键
			name:属性名
			column:列名 -->
		<id name="userId" column="user_id">
			<!-- generator:配置主键生成策略
				identity:自增mysql
				sequence:序列oracle/DB2
				uuid:32位全球唯一字符串
				
				increment:自增,不建议使用
				native:由hibernate生成主键,不建议使用
				assigned:由程序生成主键
				 -->
			<generator class="identity"/>
			
		</id>
		<!-- 使用property对普通列配置 -->
		<property name="userName" column="user_name"/>
		<property name="password" column="password"/>
		<property name="age" column="age"/>
	</class>
</hibernate-mapping>
5.在hibernate主配置文件中添加映射文件路径
6.编写代码

Hibernate对象状态:

三态:
初始态(Virgin):刚new出的对象 User user = new User();
初始态对象和hibernate无关联

持久态:调用hibernate save() update() load() get() Query对象的方法 等API时,对象会由初始态---->持久态
持久态的对象会被session进行管理,也就是和数据库建立了直接关联

游离态(处理后的状态):失去了session管理的对象
注意:
1.游离态对象仍然存在,等待被GC(Garbage Collection)垃圾回收线程回收
2.游离态对象有OID,主键值
3.游离态对象可以重新回到持久态 saveOrUpdate(Object)

Hibernate简单API

public class TestCRUD {

	private SessionFactory sf;
	
	@Before
	public void testSessionFactory(){
		//1.加载hibernate.cfg.xml
		//默认加载src下根目录下的hibernate.cfg.xml
		//为一个Configuration对象
		Configuration cfg = new Configuration().configure();
		//2.通过Configuration创建SessionFactory
		sf = cfg.buildSessionFactory();
	}
	
	@Test
	public void testAdd(){
		//2.通过SessionFactory获取Session
		Session session = sf.openSession();
		//3.开启事务,hibernate默认不会自动提交事务
		Transaction tx = session.beginTransaction();
		//4.调用hibernateAPI完成CRUD
		User user = new User();
		user.setUserName("ss");
		user.setPassword("ss");
		user.setAge(10);
		//session.save(Object):把该Java对象入库
		session.save(user);
		//5.操纵完毕后提交事务
		tx.commit();
		//6.关闭Session
		session.close();
	}

	@Test
	public void testDelete(){
		//hibernate默认按主键删除,对象主键属性必须有值
		Session session = sf.openSession();
		Transaction tx = session.beginTransaction();
		User user = new User();
		user.setUserId(5);
		//session.delete(Object):删除该对象对应的数据库记录
		session.delete(user);
		tx.commit();
		session.close();
	}
	
	@Test
	public void testQuery(){
		//按主键查询:get/load
		//使用openSession查询可以不开启事务
		Session session = sf.openSession();
		//session.get(类对象,主键值)
		User user = session.load(User.class, 11);
		System.out.println(user);
		session.close();
	}
	
	@Test
	public void testUpdate(){
		//先查后改
		Session session = sf.openSession();
		Transaction tx = session.beginTransaction();
		//查出一个User
		User user = session.load(User.class, 11);
		user.setUserName("GayP");
//		session.update(user);
		tx.commit();
		session.close();
	}
	
}
session.get/load(类对象,主键值)
get/load的区别:
1.get是立即加载,使用get会立刻向数据库发送sql语句
 load是延迟加载,在调用对象的方法或者属性前不发送sql,当调用对象的方法或者属性时才发送sql
2.get不存在的主键,返回值为null
  load会抛出ObjectNotFoundException

复杂查询:
1.按ID查:get/load
2.使用HQL进行查询
Hibernate Query Language:HQL
HQL是一种类SQL语句:
1.HQL没有表的概念,表名统一替换为类名
2.HQL没有列的概念,列名统一替换属性名
3.无select * from 类名:
from 类名 查询所有列
一个应用一般只需要一个SessionFactory
封装HibernateUtil工具类实现SessionFactory单例

先实现一个HibernateUtil类,并测试Query对象
public class HibernateUtil {
	
	private static Configuration cfg;
	private static SessionFactory sf;
	//事务写成共有的,外界需要用
	public static Transaction tx;
	
	static{
		cfg = new Configuration().configure();
		sf = cfg.buildSessionFactory();
	}
	/**
	 * 获取Session对象
	 */
	public static Session getSession(){
		Session session = sf.openSession();
		tx = session.beginTransaction();
		return session;
	}
}


public class TestQuery {
	
	@Test
	public void testAllUser(){
		Session session = HibernateUtil.getSession();
		//1.编写HQL
		String hql = "from User where userName =:username"
				+ " and password =:password";
		//2.通过session创建Query对象并传入HQL语句
		Query query = session.createQuery(hql);
		//3.调用Query对象的API完成查询
		query.setParameter("username", "GayP");
		query.setParameter("password", "ooxx1");
		List<User> users =  query.list();
		System.out.println(users==null);
		System.out.println(users.isEmpty());
		for (User user : users) {
			System.out.println(user);
			System.out.println("-----------");
		}
		HibernateUtil.tx.commit();
		session.close();
	}
	
	@Test
	public void testFindAllUser2(){
		Session session = HibernateUtil.getSession();
		//1.编写HQL
		String hql = "from User";
		//2.通过HQL创建Query对象
		Query query = session.createQuery(hql);
		Iterator<User> it = query.iterate();
		while(it.hasNext()){
			User user = it.next();
			System.out.println(user);
			System.out.println("-----------");
		}
	}
	
	@Test
	public void testQueryUserByName(){
		Session session = HibernateUtil.getSession();
		String hql = "from User where userName = ?";
		Query query = session.createQuery(hql);
		//给占位符赋值
		//注意HQL占位符从0开头
		query.setParameter(0, "GayP");
		//注意:返回值为单行记录才能使用uniqueResult()
		//uniqueResult():Object
		User user = (User) query.uniqueResult();
		System.out.println(user);
		HibernateUtil.tx.commit();
		session.close();
	}
	
	@Test
	public void testQueryUserByName2(){
		Session session = HibernateUtil.getSession();
		String hql = "from User where userName =:username"
				+ " and password =:password";
		Query query = session.createQuery(hql);
		//给占位符赋值
		query.setParameter("username", "GayP");
		query.setParameter("password", "ooxx");
		//注意:返回值为单行记录才能使用uniqueResult()
		//uniqueResult():Object
		User user = (User) query.uniqueResult();
		System.out.println(user);
		HibernateUtil.tx.commit();
		session.close();
	}
	
	
	@Test
	public void testQueryUserByName3(){
		Session session = HibernateUtil.getSession();
		String hql = "from User where userName =:username"
				+ " and password =:password";
		Query query = session.createQuery(hql);
		//把参数封装为一个map:
		//key:参数名
		//value:参数值
		Map<String, Object> parameters =
				new HashMap<String,Object>();
		parameters.put("username", "GayP");
		parameters.put("password", "ooxx");
		//给占位符赋值
		query.setProperties(parameters);
		//注意:返回值为单行记录才能使用uniqueResult()
		//uniqueResult():Object
		User user = (User) query.uniqueResult();
		System.out.println(user);
		HibernateUtil.tx.commit();
		session.close();
	}
	
	@Test
	public void testQueryUserByName4(){
		Session session = HibernateUtil.getSession();
		String hql = "from User where userName =:username"
				+ " and password =:password";
		Query query = session.createQuery(hql);
		//把参数封装为一个JavaBean:
		UserQueryBean qb = new UserQueryBean();
		qb.setUsername("GayP");
		qb.setPassword("ooxx");
		//给占位符赋值
		query.setProperties(qb);
		//注意:返回值为单行记录才能使用uniqueResult()
		//uniqueResult():Object
		User user = (User) query.uniqueResult();
		System.out.println(user);
		HibernateUtil.tx.commit();
		session.close();
	}
	
	//投影查询1:封装为JavaBean
	@Test
	public void testHeadHard1(){
		Session session = HibernateUtil.getSession();
		String hql = "select new entity.User(userName,password)"
				+ " from User";
		List<User> users = session.createQuery(hql).list();
		for (User user : users) {
			System.out.println(user);
			System.out.println("----------");
		}
		HibernateUtil.tx.commit();
		session.close();
	}
	
	@Test
	public void testHeadHard2(){
		Session session = HibernateUtil.getSession();
		String hql = "select new Map(userName,password) from User";
		//查询一行结果对应一个Map
		//多个Map的集合就是一个List
		List<Map<String, Object>> result = 
				session.createQuery(hql).list();
		for (Map<String, Object> map : result) {
			//遍历Map
			for (Entry<String, Object> entry : map.entrySet()) {
				System.out.println(entry.getKey() + ":" 
						+ entry.getValue());
			}
			//内层循环走完,一行遍历结束
			System.out.println("-------------");
		}
		HibernateUtil.tx.commit();
		session.close();
	}
	
	
}

如何给hql中的占位符赋值:
参数较少时
1.query.setParameter(“参数名”,参数值);

参数较多时
2.把参数封装成Map
query.setProperties(map);
3.把参数封装为一个JavaBean
query.setProperties(Java对象);

投影查询

查询部分列:
1.select new entity.User(userName,password) from User
把查询结果封装成JavaBean
注意:该类中必须有相应的构造
2.select new Map(属性名1,属性名2…) from 类名
把查询结果封装成Map
Map的key是下标,value就是属性值
3.hql:select 属性名1,属性名2… from 类名
使用Object[]封装查询结果:
一行记录对应一个Object[],多行记录对应一个List<Object[]>
注意:只能封装查询结果,无法查询属性名或下标。

openSession和getCurrentSession的区别

1.openSession无需配置getCurrentSession需要配置
在主配置文件中添加 <propertyname=“hibernate.current_session_context_class”>thread
current:当前线程
一个事务对应一个线程 当前事务
CurrentSession:线程绑定session
1.当前事务对应的session
2.一个事务对应一个session
事务结束:commiy rollback
session对象自动销毁(不需要再调用session.close();方法)
3.CurrentSession在事务结束后,无需也不能close该session
注意:
CurrentSession是和事务绑定的,没有事务也就没有session
获取CurrentSession必须开启事务
openSession无需开启事务
4.CurrentSession是线程安全的
openSession是线程非安全的,有可能产生线程并发问题

加载方式

一.延迟加载的概念   
当Hibernate从数据库中加载某个对象时,不加载关联的对象,
只是生成了代理对象,获取使用session中的load的方法(在没有
改变lazy属性为false的情况下)获取到的也是代理对象,所以在上
面这几种场景下就是延迟加载。

二.立即加载的概念     
当Hibernate从数据库中加载某个对象时,加载关联的对象,
生成的实际对象,获取使用session中的get的方法获取到的是实际对象。  

三.为什么要使用延迟加载     
延迟加载策略能避免加载应用程序不需要访问的关联对象,以提高
应用程序的性能。    

四.立即加载的缺点    Hibernate在查询某个对象时,立即查询与之关联的对象,我们
可以看出这种加载策略存在两大不足 
1.select的语句数目太多,需要频繁的访问数据库,会影响查询的性能。    
2.在应用程序只需要访问要的对象,而不需要访问与他关联的对象
的场景下,加载与之关联的对象完全是多余的操作,这些多余的操
作是会占内存,这就造成了内存空间的浪费。    

Hibernate在对象-关系映射问价中配置加载策略(以文件形式映射)
I.类级别:
元素中lazy属性的可选值为true(延迟加载)和false(立即加载);
元素中的lazy属性的默认值为true
II.一对多关联级别:
元素中的lazy属性的可选值为:true(延迟加载),extra(增强延迟加载)和false(立即加载);
元素中的lazy属性的默认值为true
III.多对一关联级别:
元素中lazy属性的可选值为:proxy(延迟加载),no-proxy(无代理延迟加载)和false(立即加载)
元素中的lazy属性的默认值为proxy

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值