hibernate第二天——值类型的集合(set,map,list,bag,sort,order-by),实体类型集合,关联关系,3l类型Long,inverse,级联

1、值类型的集合

集合元素是普通类型

(1)、数据存放类型

Set
        HashSet 无序,不重复

List
        有序,可重复

Map
        键值对
        HashMap 无序,不重复(以key为准)
-----------------------------------------------
数组

Bag
        无序,可重复
        List

集合映射的表结构学习路线图:
hibernate第二天——值类型的集合(set,map,list,bag,sort,order-by),实体类型集合,关联关系,3l类型Long,inverse,级联_第1张图片

(2)、映射集合属性——set

Set
        HashSet 无序,不重复

User实体:
private Integer id;
private String name;
private Set addressSet = new HashSet();


User.hbm.xml:




	
	
		
        	
		
		
		
		
		
			
			
			
		
	
	


测试app:
private static SessionFactory sessionFactory;
//初始化工厂
static {
	Configuration configuration = new Configuration();
	//读取指定的配置文件
	configuration.configure();
	//configuration.buildSessionFactory();
	ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
	sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}

@Test
public void testSave(){
	User user = new User();
	user.setName("张三");
	user.getAddressSet().add("江苏省");
	user.getAddressSet().add("江苏省");
	user.getAddressSet().add("南京市");

	//获取session
	Session session = sessionFactory.openSession();
	//开启事务
	Transaction tx =session.beginTransaction();
	session.save(user);
	//提交事务
	tx.commit();
	//关闭session,释放资源
	session.close();
}

由于set是不重复的,所以只会存在一个“江苏省”

(3)、映射集合属性——list

List
        有序,可重复

User.hbm.xml:


	
	
	


测试app:
user.getAddressList().add("江苏省");
user.getAddressList().add("南京市");
user.getAddressList().add("南京市");

由于list是允许重复的,因此会有两个”南京市“

(4)、映射集合属性——数组

User.hbm.xml:


	
	
	


测试app:

// >> 数组
user.setAddressArray(new String[] { "御富科贸园", "棠东东路" });		
System.out.println(Arrays.toString(user.getAddressArray()));

(5)、映射集合属性——MAP

User.hbm.xml:


	
	
	

测试app:
// >> Map集合
user.getAddressMap().put("公司", "御富科贸园");
user.getAddressMap().put("家庭", "棠东东路");

(6)、映射集合属性——BAG

Bag
        无序,可重复
        List

User实体:
private List addressBag = new ArrayList();

User.hbm.xml:


	
	

测试app:
// >> Bag集合
user.getAddressBag().add("御富科贸园");
user.getAddressBag().add("棠东东路");
user.getAddressBag().add("棠东东路");


使用集合属性时,一定要使用接口,而不能声明为具体的实现类。
因为经过Session操作后,集合就变成了Hibernate自己的集合实现类。


(7)、sort属性——set、map(效率低,不常用)

使用sort属性要使用有序set,TreeSet。
测试app:

sort属性:"unsorted|natural|comparatorClass"
默认为:unsorted
内存排序

User.hbm.xml:

	
	


测试app:
User user = new User();
user.setName("张三");
user.setAddressSet(new TreeSet());
user.getAddressSet().add("3江苏省");
user.getAddressSet().add("3江苏省");
user.getAddressSet().add("1南京市");

(8)、order-by属性

order-by属性:写的是order by 子句,是SQL语句,是操作的集合表。DESC降序,ASC升序。
这是在查询数据时指定orderby子句。
测试app:
User.hbm.xml:

	
	

2、实体类型的集合与关联关系

集合元素是另一个实体

(1)、一对多关联关系

只需要两张表
hibernate第二天——值类型的集合(set,map,list,bag,sort,order-by),实体类型集合,关联关系,3l类型Long,inverse,级联_第2张图片
对于一对多的关系,需要考虑的操作:

  • 保存,有关联关系
  • 获取,可以获取到关联的对方
  • 解除关联关系
  • 删除对象,对关联对象的影响
没有外键的可以放弃维护,有外键的必须维护。被依赖的要先保存,不被依赖的后保存。

Department.hbm.xml:




    
        
        
            
            
        
        
        

        
        
            
            
        
    


Employee.hbm.xml:




    
        
        
            
            
        
        
        

        
    


测试App:
package cn.itcast.f_hbm_oneToMany;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
			.addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
			.buildSessionFactory();

	// 保存,有关联关系
	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 新建对象
		Department department = new Department();
		department.setName("开发部");

		Employee employee1 = new Employee();
		employee1.setName("张三");

		Employee employee2 = new Employee();
		employee2.setName("李四");

		// 关联起来
		employee1.setDepartment(department);
		employee2.setDepartment(department);
		department.getEmployees().add(employee1);
		department.getEmployees().add(employee2);

		// 保存
//		session.save(employee1);
//		session.save(employee2);
		session.save(department); // 保存部门

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 获取,可以获取到关联的对方
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 获取一方,并显示另一方信息
		Department department = (Department) session.get(Department.class, 1);
		System.out.println(department);
		System.out.println(department.getEmployees());

		// Employee employee = (Employee) session.get(Employee.class, 1);
		// System.out.println(employee);
		// System.out.println(employee.getDepartment());

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 解除关联关系
	@Test
	public void testRemoveRelation() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// // 从员工方解除
		// Employee employee = (Employee) session.get(Employee.class, 1);
		// employee.setDepartment(null);

		// 从部门方解除(与inverse有关系,为false时可以解除)
		Department department = (Department) session.get(Department.class, 1);
		department.getEmployees().clear();

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 删除对象,对关联对象的影响
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// // 删除员工方(多方),对对方没有影响
		// Employee employee = (Employee) session.get(Employee.class,2);
		// session.delete(employee);

		// 删除部门方(一方)
		// a, 如果没有关联的员工:能删除。
		// b, 如果有关联的员工且inverse=true,由于不能维护关联关系,所以会直接执行删除,就会有异常
		// c, 如果有关联的员工且inverse=false,由于可以维护关联关系,他就会先把关联的员工的外键列设为null值,再删除自己。
		Department department = (Department) session.get(Department.class, 4);
		session.delete(department);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}
}

级联:用于一对多,一对一;不用于多对多,多对一







维护关联关系:
对于一对多:
就是设置 外键列的值。
对于多对多:
就是插入或删除 中间表中的记录。

(2)、多对多关联关系

需要三张表,多出一张中间表,两个外键
hibernate第二天——值类型的集合(set,map,list,bag,sort,order-by),实体类型集合,关联关系,3l类型Long,inverse,级联_第3张图片

Student.hbm.xml:




	
	
		
        	
		
		
		
		
		
			
			
		
			
	
	


Teacher.hbm.xml:




	
	
		
        	
		
		
		
		
		
			
			
		
		
	
	


测试APP:
package cn.itcast.g_hbm_manyToMany;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Student.class)// 添加Hibernate实体类(加载对应的映射文件)
			.addClass(Teacher.class)// 添加Hibernate实体类(加载对应的映射文件)
			.buildSessionFactory();

	// 保存,有关联关系
	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 新建对象
		Student student1 = new Student();
		student1.setName("王同学");

		Student student2 = new Student();
		student2.setName("李同学");

		Teacher teacher1 = new Teacher();
		teacher1.setName("赵老师");

		Teacher teacher2 = new Teacher();
		teacher2.setName("蔡老师");

		// 关联起来
		student1.getTeachers().add(teacher1);
		student1.getTeachers().add(teacher2);
		student2.getTeachers().add(teacher1);
		student2.getTeachers().add(teacher2);

		teacher1.getStudents().add(student1);
		teacher1.getStudents().add(student2);
		teacher2.getStudents().add(student1);
		teacher2.getStudents().add(student2);

		// 保存
		session.save(student1);
		session.save(student2);
		session.save(teacher1);
		session.save(teacher2);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 获取,可以获取到关联的对方
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 获取一方,并显示另一方信息
		Teacher teacher = (Teacher) session.get(Teacher.class, 3L);
		System.out.println(teacher);
		System.out.println(teacher.getStudents());

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();

	}

	// 解除关联关系
	@Test
	public void testRemoveRelation() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 如果inverse=false就可以解除,如果为true就不可以解除
		Teacher teacher = (Teacher) session.get(Teacher.class, 3L);
		teacher.getStudents().clear();

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 删除对象,对关联对象的影响
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// a, 如果没有关联的对方:能删除。
		// b, 如果有关联的对方且inverse=false,由于可以维护关联关系,他就会先删除关联关系,再删除自己。
		// c, 如果有关联的对方且inverse=true,由于不能维护关联关系,所以会直接执行删除自己,就会有异常。
		Teacher teacher = (Teacher) session.get(Teacher.class, 9L);
		session.delete(teacher);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

}


双向关联
单向关联:
单向多对一
单向一对多
单向多对多


3、对象的状态

临时状态测试(transient):
        与数据库没有对应,跟Session没有关联。
        一般是新new出的对象。
Department department = new Department();
department.setName("研发部");
System.out.println(department.getId());
session.save(department);
System.out.println(department.getId());
刚开始得到的ID为null,后面得到的ID为11;
save()的过程就是将临时状态进行持久化!


持久化状态(Persist):
        对象在Session的管理之中,最终会有对应的数据库记录。
        特点:
                (1)、有OID(唯一标识符)
(2)、对对象的修改会同步到数据库。
在session内的代码:
//获取一方
Employee employee = (Employee) session.get(Employee.class, 9);
System.out.println(employee);

employee.setName("i");
会直接修改掉数据库中的数据


游离状态测试(Detached):
        数据库中有对应记录,但对象不在Session管理之中。
        修改此状态对象时数据库不会有变化。


删除状态(Removed):
         执行了delete()后的对象。




hibernate第二天——值类型的集合(set,map,list,bag,sort,order-by),实体类型集合,关联关系,3l类型Long,inverse,级联_第4张图片


  • save():把临时状态变为持久化状态(交给Sessioin管理)   会生成:insert into ...
  • update():把游离状态变为持久化状态                                   会生成:update ...
  • saveOrUpdate():把临时或游离状态转为持久化状态            会生成:insert into 或 update ...     
  • delete():把持久化或游离转为删除状态                                 会生成:delete ...
  • get():获取数据,是持久化状态                                             会生成:select ... where id=?
  • load():获取数据,是持久化状态                                           会生成:select ... where 

一、操作实体对象的
save()
update()
saveOrUpdate()
delete()

二、操作缓存的
clear()
evict()  驱逐单个对象
flush()  执行sql语句,提交事务默认先进行flush。save和查询get比较特殊会直接flush


三、查询实体对象的
get()
load()           
createQuery()
createCriteria()




加载方式               返回值                          如果数据不存在
------------------------------------------------------------------------------
get 立即加载         真实对象或null                返回null
load 延迟加载       代理对象                          抛异常


package cn.itcast.h_session_method;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(User.class)// 添加Hibernate实体类(加载对应的映射文件)
			.buildSessionFactory();

	// save():把临时状态变为持久化状态(交给Sessioin管理)
	// 会生成:insert into ...
	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		User user = new User(); // 临时状态
		user.setName("test");
		session.save(user); // 变为了持久化状态

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();

		user.setName("李四"); // 游离状态
		System.out.println(user.getName()); // 游离状态
	}

	// update():把游离状态变为持久化状态
	// 会生成:update ...
	// 在更新时,对象不存在就报错
	@Test
	public void testUpdate() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		User user = (User) session.get(User.class, 1);
		System.out.println(user.getName()); // 持久化状态

		// session.clear(); // 清除Session中所有的对象
		session.evict(user); // 清除Session中一个指定的对象

		user.setName("newname3");
		session.update(user);
		System.out.println("----");
		// session.flush(); // 刷出到数据库

		// --------------------------------------------
		session.getTransaction().commit(); // 
		session.close();
	}

	// saveOrUpdate():把临时或游离状态转为持久化状态
	// 会生成:insert into 或 update ...
	// 在更新时,对象不存在就报错
	// 本方法是根据id判断对象是什么状态的:如果id为原始值(对象的是null,原始类型数字是0)就是临时状态,如果不是原始值就是游离状态。
	@Test
	public void testSaveOrUpdate() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		User user = new User();
		user.setId(3); // 自己生成一个游离状态对象
		user.setName("newName");

		session.saveOrUpdate(user);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// delete():把持久化或游离转为删除状态
	// 会生成:delete ...
	// 如果删除的对象不存在,就会抛异常
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// User user = (User) session.get(User.class, 2); // 持久化

		User user = new User();
		user.setId(300);

		session.delete(user);
		session.flush();

		System.out.println("---");

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// get():获取数据,是持久化状态
	// 会生成:select ... where id=?
	// 会马上执行sql语句
	// 如果数据不存在,就返回null
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		User user = (User) session.get(User.class, 5); // 持久化
		System.out.println(user.getClass());
		// System.out.println("---");
		// System.out.println(user.getName());

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// load():获取数据,是持久化状态
	// 会生成:select ... where id=?
	// load()后返回的是一个代理对象,要求类不能是final的,否则不能生成子类代理,就不能使用懒加载功能了。
	// 让懒加载失效的方式:一、把实体写成final的;二、在hbm.xml中写
	// 不会马上执行sql语句,而是在第1次使用非id或class属性时执行sql。
	// 如果数据不存在,就抛异常:ObjectNotFoundException
	@Test
	public void testLoad() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		User user = (User) session.load(User.class, 5);
		System.out.println(user.getClass());
		System.out.println("---");
		System.out.println(user.getId());
		System.out.println(user.getName());
		// System.out.println(user.getName());

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 操作大量数据,要防止Session中对象过多而内存溢出
	@Test
	public void testBatchSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		for (int i = 0; i < 30; i++) {
			User user = new User();
			user.setName("测试");
			session.save(user);

			if (i % 10 == 0) {
				session.flush(); // 先刷出
				session.clear(); // 再清空
			}
		}

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

}

4、回顾

一、集合映射。
        类型          Java中声明                映射元素
        -------------------------------------------------------
        Set                  Set                          
        List                  List                          
        Map                 Map                        
        数组                 ...[]                          
        Bag                 List/Collection        
        --------------------------------------------------------
        要说明的信息有:
        1,只要有集合,就一定有集合表。
        2,集合外键。
        3,集合元素。
        4,对于List和数组,还需要多一个索引列。
        5,对于Map,还需要多一个key列。

        值类型的集合。
        实体类型的集合。


二、关联关系映射(要说明的信息有什么)。
         一对多:
                1,属性名
                2,集合外键
                3,关联的实体类型(one-to-many  class="")

         多对一:
                1,属性名
                2,外键列名
                3,关联的实体类型

          多对多:
                1,属性名
                2,中间表
                3,集合外键:引用当前对象表主键值的那外外键
                4,关联的实体类型
                5,另一个外键:引用关联实体表主键的那个外键。


          一些重要的属性:
                inverse:
                        是否放弃维护关联关系。
                        默认是false,表示可以维护。
                        实体类型的集合映射中可以使用(一对多、多对多)。

                sort:
                        在内存中排序(类似于TreeSet)
                        默认为unsorted,即不排序。
                        在无序的集合映射中可以使用。

                order-by:
                        使用数据库排序,即在SQL中增加orderby子句(类似于LinkedHashSet)。
                        默认不排序,这里指定的是sql语句中的orderby子句。
                        在无序的集合映射中可以使用。

                cascade:
                        级联。
                        默认为none。
                        在所有的关联关系映射中可以使用。
                        常用的值:all, save-update, delete, none.

三、Session中的方法。
         对象的状态:
                                 Session中          数库中
                ---------------------------------------------------
                临时              无                     无
                持久化          有                     最终会有
                游离              无                     有
                删除              调用了delete()方法后


        1,操作实体对象的
                save()
                update()
                saveOrUpdate()
                delete()

        2,操作缓存的
                clear()       清空Session缓存,不会执行sql语句。
                evict()
                flush()       马上执行sql语句,不会清楚Session缓存。

        3,查询实体对象的
                get()
                load()
                createQuery()
                createCriteria()


你可能感兴趣的:(hibernate学习之路)