• Hibernate学习---第六节:数组&list&map&set的映射配置


    1、实体类,代码如下:

    package learn.hibernate.bean;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 持久化类设计
     * 注意:
     *         持久化类通常建议要有一个持久化标识符(ID)
     *         持久化标识符通常建议使用封装类(例如:Integer  因为基本类型存在默认值)
     *         持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的)
     *         属性通常建议提供  getter/setter 方法
     *         持久化类不能使用 final 修饰
     *         持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
     *              如下:ArrayList list = new ArrayList();  不行
     *                 List list = new ArrayList(); 可行
     */
    public class Person {
    
        private Integer id;
        private String name;
        private int age;
        private int passwork;
        private Date birthday;
        /**
         * 数组  同构类型数据 (效率低)
         * 通过 下标 访问数组中的元素
         */
        private String[] myArr;
        /**
         * List 
         * 通过 下标 访问数组中的元素
         */
        private List myList;
        /**
         * 通过 key 访问value
         */
        private Map myMap;
        /**
         * 只有值本身
         */
        private Set mySet;
        
        public Person() {
            
        }
        
        public Person(String name, int age, int passwork, Date birthday) {
            super();
            this.name = name;
            this.age = age;
            this.passwork = passwork;
            this.birthday = birthday;
        }
        
        @Override
        public String toString() {
            return "Person [id=" + id + ", name=" + name + ", age=" + age
                    + ", passwork=" + passwork + ", birthday=" + birthday + "]";
        }
        
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public int getPasswork() {
            return passwork;
        }
        public void setPasswork(int passwork) {
            this.passwork = passwork;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String[] getMyArr() {
            return myArr;
        }
    
        public void setMyArr(String[] myArr) {
            this.myArr = myArr;
        }
    
        public List getMyList() {
            return myList;
        }
    
        public void setMyList(List myList) {
            this.myList = myList;
        }
    
        public Map getMyMap() {
            return myMap;
        }
    
        public void setMyMap(Map myMap) {
            this.myMap = myMap;
        }
    
        public Set getMySet() {
            return mySet;
        }
    
        public void setMySet(Set mySet) {
            this.mySet = mySet;
        }
        
    }

    2、映射文件,代码如下:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="learn.hibernate.bean">
        <class name="Person" table="t_person">
            <id name="id" column="person_id">
                <generator class="native"/>
            </id>
            <property name="name" column="t_name"/>
            <property name="age"/>    
            <property name="passwork"/>
            <property name="birthday"/>
            <!-- 数组的映射配置  table 可选-->
            <array name="myArr" table="t_array">
                <!-- 
                    t_array 表保存数组中的数据,需要和 t_person 表建立关联关系(一对多),所有需要一个 key
                    list-index 指定数组下标存储列的映射
                    element 表示数组中的元素存储列的映射
                 -->
                <key column="id"/>
                <list-index column="arr_indexs"/>
                <element column="arr_values"/>
            </array>
            <!-- list 的映射配置 list 和 array 一样-->
            <list name="myList">
                <key column="id"/>
                <list-index column="list_indexs"/>
                <element column="list_values"/>
            </list>
            <!-- map 的映射配置 -->
            <map name="myMap">
                <!-- 
                    map-key 指定 map 集合的 key 数据存储的列映射,并指定类型
                    element 表示 map 中的元素存储列的映射
                 -->
                <key column="id"/>
                <map-key column="map_keys" type="string"/>
                <element column="map_values"/>
            </map>
            <!-- set 的映射配置  
                set没有下标和 key,只需要元素即可
             -->
            <set name="mySet">
                <key column="id"/>
                <element column="set_values"/>
            </set>
        </class>
    </hibernate-mapping>

    3、测试代码:

    package learn.hibernate.test;
    
    import static org.junit.Assert.*;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import learn.hibernate.bean.Person;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.service.ServiceRegistry;
    import org.hibernate.service.ServiceRegistryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    public class TestHibernate {
    
        SessionFactory factory = null;
        Session session = null;
        Transaction tx = null;
        
        /**
         * 测试之前初始化数据
         * @throws Exception
         */
        @SuppressWarnings("deprecation")
        @Before
        public void setUp() throws Exception {
            System.out.println("---------初始化数据----------");
            
            Configuration config = new Configuration().configure();
            ServiceRegistry sr = new ServiceRegistryBuilder()
            .applySettings(config.getProperties()).buildServiceRegistry();
            factory = config.buildSessionFactory(sr);
            session = factory.openSession();
        }
    
        /**
         * 测试之后释放(销毁)数据
         * @throws Exception
         */
        @After
        public void tearDown() throws Exception {
            System.out.println("---------释放数据----------");
            if(session.isOpen()){
                session.close();
            }
        }
        
        @Test
        public void testAdd(){
            Person p = new Person("June",22,123456,new Date());
            
            String[] myArr = {"A","B","C","D"};
            
            List myList = new ArrayList();
            myList.add("北京");
            myList.add("上海");
            myList.add("长沙");
            myList.add("深圳");
            
            Map myMap = new HashMap();
            myMap.put(1, "中国");
            myMap.put(2, "湖南");
            myMap.put(3, "郴州");
            myMap.put(4, "桂阳");
            
            Set mySet = new HashSet();
            mySet.add("跑步");
            mySet.add("游泳");
            mySet.add("篮球");
            
            p.setMyArr(myArr);
            p.setMyList(myList);
            p.setMyMap(myMap);
            p.setMySet(mySet);
            
            tx = session.beginTransaction();
            session.persist(p);
            tx.commit();
        }
    }

    4、测试,会发现报错:

    org.hibernate.MappingException: No type name
        at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:319)
        at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:310)
        at org.hibernate.mapping.Collection.validate(Collection.java:315)
        at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:89)
        at org.hibernate.cfg.Configuration.validate(Configuration.java:1362)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849)
        at learn.hibernate.test.TestHibernate.setUp(TestHibernate.java:44)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
    
    java.lang.NullPointerException
        at learn.hibernate.test.TestHibernate.tearDown(TestHibernate.java:55)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    原因是没有给映射文件中的字段指定数据类型

    修改映射文件,代码如下:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="learn.hibernate.bean">
        <class name="Person" table="t_person">
            <id name="id" column="person_id">
                <generator class="native"/>
            </id>
            <property name="name" column="t_name"/>
            <property name="age"/>    
            <property name="passwork"/>
            <property name="birthday"/>
            <!-- 数组的映射配置  table 可选-->
            <array name="myArr" table="t_array">
                <!-- 
                    t_array 表保存数组中的数据,需要和 t_person 表建立关联关系(一对多),所有需要一个 key
                    list-index 指定数组下标存储列的映射
                    element 表示数组中的元素存储列的映射
                 -->
                <key column="id"/>
                <list-index column="arr_indexs"/>
                <element type="java.lang.String" column="arr_values"/>
            </array>
            <!-- list 的映射配置 list 和 array 一样-->
            <list name="myList">
                <key column="id"/>
                <list-index column="list_indexs"/>
                <element type="java.lang.String" column="list_values"/>
            </list>
            <!-- map 的映射配置 -->
            <map name="myMap">
                <!-- 
                    map-key 指定 map 集合的 key 数据存储的列映射,并指定类型
                    element 表示 map 中的元素存储列的映射
                 -->
                <key column="id"/>
                <map-key type="java.lang.String" column="map_keys"/>
                <element type="java.lang.String" column="map_values"/>
            </map>
            <!-- set 的映射配置  
                set没有下标和 key,只需要元素即可
             -->
            <set name="mySet">
                <key column="id"/>
                <element type="java.lang.String" column="set_values"/>
            </set>
            
            <!-- bag 可以重复存放数据,但是修改和删除的时候没有 id 值,所以不知道具体是哪一条,所以会将全部数据删除,重新插入新数据 -->
            <!-- <bag name="items" table="t_item">
                <key column="id"/>
                <element type="java.lang.String" column="name"/>
            </bag> -->
            
            <!-- bag 的一个升级  数据带ID -->
            <!-- <idbag name="items" table="t_item">
                <collection-id type="java.lang.String" column="cid">
                    <generator class="uuid.hex"/>
                </collection-id>
                <key column="id"/>
                <element type="java.lang.String" column="name"/>
            </idbag> -->
        </class>
    </hibernate-mapping>

    所有的有序集合类(maps,lists,arrays)都拥有一个由 <key> 和 <index> 组成的主键。这种情况下集合类的更新是非常高效的 — 主键已经被有效的索引,因此当 Hibernate 试图更新或删除一行时,可以迅速找到该行数据。

    集合(sets)的主键由 <key> 和其他元素字段构成。对于有些元素类型来说,这很低效,特别是组合元素或者大文本、大二进制字段;数据库可能无法有效的对复杂的主键进行索引。另一方面,对于一对多、多对多关联,特别是合成的标识符来说,集合也可以达到同样的高效性能。( 附注:如果你希望 SchemaExport 为你的 <set> 创建主键,你必须把所有的字段都声明为 not-null="true"。)

    <idbag> 映射定义了代理键,因此它总是可以很高效的被更新。事实上,<idbag> 拥有着最好的性能表现。

    Bag 是最差的。因为 bag 允许重复的元素值,也没有索引字段,因此不可能定义主键。 Hibernate 无法判断出重复的行。当这种集合被更改时,Hibernate 将会先完整地移除 (通过一个(in a single DELETE))整个集合,然后再重新创建整个集合。因此 Bag 是非常低效的。

    请注意:对于一对多关联来说,“主键”很可能并不是数据库表的物理主键。但就算在此情况下,上面的分类仍然是有用的。(它仍然反映了 Hibernate 在集合的各数据行中是如何进行“定位”的。)

    文字部分来自:

    http://ears.iteye.com/blog/1508557

    也可以查看:

    http://www.cnblogs.com/otomedaybreak/archive/2012/01/18/2325993.html

  • 相关阅读:
    python之处理excel表格
    Django下JWT的使用
    Flask的上下文管理
    模块循环引用
    博客声明及意义
    IPTABLES--iptables
    挂载U盘
    tar压缩解压
    iconv字符编码转换
    VirtualBox设置共享文件夹
  • 原文地址:https://www.cnblogs.com/hwlsniper/p/4271182.html
Copyright © 2020-2023  润新知