• hibernate---关联关系的 crud_cascade_fetch


    CRUD怎么写??

    存user信息, 自动存group信息

    user.java

    package com.bjsxt.hibernate;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToOne;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="t_user")
    public class User {
    	private int id;
    	private String name;
    	private Group group;
    	@ManyToOne(cascade={CascadeType.ALL})
    	public Group getGroup() {
    		return group;
    	}
    	public void setGroup(Group group) {
    		this.group = group;
    	}
    	@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;
    	}
    }
    

    group.java:

    package com.bjsxt.hibernate;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="t_group")
    public class Group {
    	private int id;
    	private String name;
    	private Set<User> users = new HashSet<User>();
    	@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;
    	}
    	@OneToMany(mappedBy="group",
    		cascade={CascadeType.ALL}
    		)
    	
    	public Set<User> getUsers() {
    		return users;
    	}
    	public void setUsers(Set<User> users) {
    		this.users = users;
    	}
    }
    

    hibernate.cfg.xml:

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://hibernate.sourceforge.net/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/hibernate</property>
            <property name="connection.username">root</property>
            <property name="connection.password">linda0213</property>
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
           <!--
            <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
            <property name="connection.url">jdbc:oracle:thin:@localhost:1521:SXT</property>
            <property name="connection.username">scott</property>
            <property name="connection.password">tiger</property>
          	<property name="dialect">org.hibernate.dialect.OracleDialect</property>
           -->
    
            <!-- JDBC connection pool (use the built-in) -->
            <property name="connection.pool_size">1</property>
    
            
    
            <!-- Enable Hibernate's automatic session context management -->
            <property name="current_session_context_class">thread</property>
    
            <!-- Disable the second-level cache  -->
            <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    
            <!-- Echo all executed SQL to stdout -->
            <property name="show_sql">true</property>
            <property name="format_sql">true</property>
    
            <!-- Drop and re-create the database schema on startup
            <property name="hbm2ddl.auto">update</property>
    		 -->
            <!--  
            
    		<mapping resource="com/bjsxt/hibernate/Group.hbm.xml"/>
    		 <mapping resource="com/bjsxt/hibernate/User.hbm.xml"/>
    		 -->
    		 <mapping class="com.bjsxt.hibernate.Group"/>
    		<mapping class="com.bjsxt.hibernate.User"/>
    		
        </session-factory>
    
    </hibernate-configuration>
    

    test文件:

    package com.bjsxt.hibernate;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.AnnotationConfiguration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    public class HibernateORMappingTest {
    	private static SessionFactory sessionFactory;
    	
    	@BeforeClass
    	public static void beforeClass() {
    		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
    		sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    	}
    	@AfterClass
    	public static void afterClass() {
    		sessionFactory.close();
    	}
    	
    	@Test
    	public void testSaveUser() {
    		User u = new User();
    		u.setName("u1");
    		Group g = new Group();
    		g.setName("g1");
    		u.setGroup(g);
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		//s.save(g);
    		s.save(u);
    		s.getTransaction().commit();
    	}
    	
    	@Test
    	public void testSchemaExport() {
    		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
    	}
    	
    	public static void main(String[] args) {
    		beforeClass();
    	}
    }
    

    如果设定group同时更新user的话:

    @Test
    	public void testSaveGroup() {
    		User u1 = new User();
    		u1.setName("u1");
    		User u2 = new User();
    		u2.setName("u2");
    		Group g = new Group();
    		g.setName("g1");
    		g.getUsers().add(u1);
    		g.getUsers().add(u2);
    		u1.setGroup(g);
    		u2.setGroup(g);
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		//s.save(g);
    		s.save(g);
    		s.getTransaction().commit();
    	}
    

    铁律:双向关系,必须设置双向关联. 双向一定要设置MappedBy

    get/load:

    从多里会自动被一取出来,即, 取user, 会取出group

    遵循原则: 默认, 多对一 eager, 一对多 lazy.

    @Test
    	public void testGetUser() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.get(User.class, 1);
    		
    		s.getTransaction().commit();
    		System.out.println(u.getGroup().getName());
    	}
    

    从一取, 不会取, 因为cascade的all不影响读取. 只管CUD, 增删改

    fetch影响读取. 管load,get等读取

    想取多的话: 可以改group.java:

    fetch=FetchType.EAGER.  LAZY是默认不取.

    所以从多取一 默认是EAGER

    从一取多, 默认是lazy, 因为数据多.

    @OneToMany(mappedBy="group",
    		cascade={CascadeType.ALL},
    	 	fetch=FetchType.EAGER
    		)
    	
    	public Set<User> getUsers() {
    		return users;
    	}
    

    test.java:

    @Test
    	public void testGetGroup() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		Group g = (Group)s.get(Group.class, 1);
    		s.getTransaction().commit();
    		for(User u : g.getUsers()) {
    			System.out.println(u.getName());
    		}
    	}
    

      

    lazy加载的报错问题: 因为commit后session结束, 不能再链接数据库获取信息了, 得把下面访问group数据库的信息放在commit上面.

    @Test
    	public void testLoadUser() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.load(User.class, 1);
    		
    		s.getTransaction().commit();
    		System.out.println(u.getGroup().getName());
    		
    	}
    

    Load的lazy和eager的区别:

    test代码:

    @Test
    	public void testLoadUser() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.load(User.class, 1);
    		System.out.println(u.getGroup().getName());
    		s.getTransaction().commit();
    		
    	}
    

    user.java如果改成lazy的话:

    @ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
    	public Group getGroup() {
    		return group;
    	}
    

    运行时: 

    1. user对group是 lazy时: 先select user, 再join user 和group

    2. user对group是eager时, 结果是先  join user 和group, 再select user.

    因为是eager会先join, 由于group里又有一个eager,所以又取了一遍user, 所以取的时候, 只要一边设置eager就可以了. 所以默认的话, 一对多默认是 lazy, 多对一默认是eager.

    XML也有对上面问题的控制, 在set里设置一个inverse="true"

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    	<class name="com.bjsxt.hibernate.Group" table="t_group">
    		<id name="id">
    			<generator class="native"></generator>
    		</id>
    		
    		<property name="name"></property>
    		<set name="users" inverse="true">
    			<key column="groupId"></key>
    			<one-to-many class="com.bjsxt.hibernate.User"/>
    		</set>
        </class>
    	
    </hibernate-mapping>
    

      

     update:

    会同时更新user和group

    之所以级联更新, 是因为user.java里有@ManyToOne(cascade={CascadeType.ALL})

    @Test
    	public void testUpdateUser() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.get(User.class, 1);
    		
    		s.getTransaction().commit();
    		
    		u.setName("user");
    		u.getGroup().setName("group");
    		
    		Session s2 = sessionFactory.getCurrentSession();
    		s2.beginTransaction();
    		s2.update(u);
    		
    		s2.getTransaction().commit();
    	}
    

      

    delete: user里有u1, u2, group里是g1, u1,u2 都是g1.

    结果两个表的数据都被删了. 因为删除u1时关联group 的g1, 删除g1的时候又级联的删除了u2.

    @Test
    	public void testDeleteUser() {		
    		testSaveGroup();		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.load(User.class, 2);
    		s.delete(u);
    		s.getTransaction().commit();		
    	}
    

    所以现在的O/R mapping的编程模型有

    a)映射模型 : jpa annotation (最常用), hibernate annotation extension, hibernate xml, jpa xml

    b)编程接口: 增删改查的接口,  jpa 接口 , hibernate 接口

    c)数据查询:

       1. HQL

       2. EJBQL(JP QL)

    所以现在开发模式是jpa annotation和hibernate的编程接口.

    解决方法: 先设定关系为null, 再删除:

    @Test
    	public void testDeleteUser() {		
    		testSaveGroup();		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.load(User.class, 2);
    		u.setGroup(null);
    		s.delete(u);		
    		s.getTransaction().commit();		
    	}
    

    第二种方法:用createQuery.

    @Test
    	public void testDeleteUser() {		
    		testSaveGroup();		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		User u = (User)s.load(User.class, 2);
    		s.createQuery("delete from User u where u.id = 2").executeUpdate();
    		s.getTransaction().commit();		
    	}
    

    删除group的情况: cascade all所以级联全部删除

    @Test
    	public void testDeleteGroup() {
    		
    		testSaveGroup();
    		
    		Session s = sessionFactory.getCurrentSession();
    		s.beginTransaction();
    		//User u = (User)s.load(User.class, 1);
    		//u.setGroup(null);
    		//s.delete(u);
    		Group g = (Group)s.load(Group.class, 1);
    		s.delete(g);
    		//s.createQuery("delete from User u where u.id = 1").executeUpdate();
    		s.getTransaction().commit();
    		
    	}
    

      

      

      

      

      

  • 相关阅读:
    2018-04-27 搭建Python官方文档翻译环境-汉化示例代码
    2018-04-21 搭建Python官方文档翻译环境
    2018-01-19 Xtext试用: 5步实现一个(中文)JVM语言
    2018-02-27 "Literate Programming"一书摘记之一
    2018-02-18 Antlr4实现简单语言之条件语句
    2018-02-17 中文代码示例[译]Scala中创建隐式函数
    2018-02-16 中文代码示例之冒泡算法, 后感
    C code example for strdup
    Hash table: why size should be prime?
    Hash table lengths and prime numbers
  • 原文地址:https://www.cnblogs.com/wujixing/p/5422318.html
Copyright © 2020-2023  润新知