zoukankan      html  css  js  c++  java
  • (转)Hibernate框架基础——映射普通属性

    http://blog.csdn.net/yerenyuan_pku/article/details/52739871

    持久化对象与OID

    对持久化对象的要求

    1. 提供一个无参的构造器。使Hibernate可以使用Constructor.newInstance()来实例化持久化类。
    2. 提供一个标识属性(identifier property)。通常映射为数据库表的主键字段。如果没有该属性,一些功能将不起作用,如:Session.saveOrUpdate()。
    3. 为类的持久化字段声明访问方法(get/set)。Hibernate对JavaBean风格的属性实行持久化。
    4. 使用非final类。在运行时生成代理是Hibernate的一个重要的功能。如果持久化类没有实现任何接口,Hibnernate使用CGLIB生成代理。如果使用的是final类,则无法生成CGLIB代理。
    5. 重写eqauls()和hashCode()方法。如果需要把持久化类的实例放到Set中(当需要进行关联映射时),则应该重写这两个方法。

    例,我们可在cn.itcast.c_hbm_property包下创建这样一个持久化类——User.java。

    /**
     * 实体
     */
    public class User {
        private int id;
        private String name;
    
        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;
        }
    
        @Override
        public String toString() {
            return "[User: id=" + id + ", name=" + name + "]";
        }
    }

    OID

    为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫做对象标识(Object identifier-OID)。

    对象/关系数据库映射文件(hbm.xml)

    Hibernate采用XML格式的文件来指定对象和关系数据之间的映射。在运行时Hibernate将根据这个映射文件来生成各种SQL语句。映射文件的扩展名为”.hbm.xml”。 
    映射文件示例: 

    持久化类的属性及属性映射(普通属性)

    对应于cn.itcast.c_hbm_property包下的持久化类——User.java,我们应在该包下创建出对象/关系数据库映射文件——User.hbm.xml。

    <?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="cn.itcast.c_hbm_property">
        <!-- 
            name属性:哪个类
            table属性:对应哪个表,如果不写,默认的表名就是类的简单名称
        -->
        <class name="User" table="t_user">
            <id name="id" type="int" column="id">
                <generator class="native"/>
            </id>
            <property name="name" type="string" column="name" length="20" not-null="true" /> 
        </class>
    </hibernate-mapping>

    映射配置:

    <property name="name" type="string" column="name" length="20" not-null="true" /> 

    即为映射的普通属性,普通属性指数据库中的基本类型,如字符串、日期、数字等。下面我们就来详解<property ... />元素中的各个属性:

    • name属性:对象中的属性名,必须要有
    • type属性:类型,如果不写,Hibernate会自动检测。可以写java中类的全名或是写hibernate类型。
    • column属性:对应表中的列名,如果没写,默认为属性名。
    • length属性:长度,不是所有的类型都有长度属性,比如varchar有,但int没有,如果不写默认为255。
    • not-null属性:非空约束,默认为false。

    所以上面的映射配置,直接写成这样干巴巴的配置:

    <property name="name" />

    也是可以的。 
    单单是编写上面这样一个映射文件——User.hbm.xml,涉及到的知识点还是蛮多的,下面我们一一讲解。

    Hibernate的映射类型

    内置映射类型

    Hibernatejavasql取值范围
    integer/int java.lang.Integer/int INTEGER 4
    long java.lang.Long/long BIGINT 8
    short java.lang.Short/short SMALLINT 2
    byte java.lang.Byte/byte TINYINT 1
    float java.lang.Float/float FLOAT 4
    double java.lang.Double/double DOUBLE 8
    big_decimal java.math.BigDecinimal NUMERIC 8位含2位小数部分
    character char/java.lang.Character/java.lang.String CHAR(1) 定长字符
    string java.lang.String VARCHAR 变长串
    boolean boolean/java.lang.Boolean BIT 布尔
    yes_no boolean/java.lang.Boolean CHAR(1) 布尔
    true_fasle boolean/java.lang.Boolean CHAR(1) 布尔

    java时间和日期类性

    Hibernatejavasql取值范围
    date java.util.Date/java.sql.Date DATE YYYY-MM-DD
    time java.util.Date/java.sql.Time TIME HH:MM:SS
    timestamp java.util.Date/java.sql.timestamp TIMESTAMP YYYYMMDDHHMMSS
    calendar java.util.Calendar TIMESTAMP YYYYMMDDHHMMSS
    calendar_date java.util.Calendar DATE YYYY-MM-DD

    大对象类型的映射

    Hibernatejavasql
    binary byte[] VARBINARY(BLOB)
    text String CLOB
    serializable 实现类 BARBINARY(BLOB)
    clob java.sql.Clob CLOB
    blob java.sql.Blob BLOB

    JDK自带的个别java类的映射类型

    Hibernatejavasql
    class java.lang.Class VARCHAR
    locale java.util.Locale VARCHAR
    timezone java.util.TimeZone VARCHAR
    currency java.util.Currency VARCHAR

    设置类的包名

    如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置<hibernate-mapping>元素的package属性,以避免为每个类提供完整的类名。 
    指定类的全限定名: 
     
    <hibernate-mapping>元素中指定package属性,就只需指定简单类名了: 

    处理sql引用表示符

    在实际开发中,我们要编写的持久化类不会这么简单,也就是说User类不会只有

    private int id;
    private String name;

    这两个字段。通常它含有的字段挺多的,例如:

    /**
     * 实体
     */
    public class User {
        private int id;
        private String name;
        private Integer age;
        private Date birthday; // 生日
        private String desc; // 一大段说明
    
        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 Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        @Override
        public String toString() {
            return "[User: id=" + id + ", name=" + name + "]";
        }
    }

    我们接下来就要修改映射文件——User.hbm.xml了。

    <?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="cn.itcast.c_hbm_property">
        <!-- 
            name属性:哪个类
            table属性:对应哪个表,如果不写,默认的表名就是类的简单名称
        -->
        <class name="User" table="t_user">
            <id name="id" type="int" column="id">
                <generator class="native"/>
            </id>
    
            <property name="name" type="string" column="name" length="20" not-null="true" /> 
    
            <property name="age" type="int" column="age_" />
    
            <property name="birthday" type="date" column="birthday_" />
    
            <!-- 指定使用text类型时,最好再指定length,以确定生成的SQL类型是能够存放指定数量的字符的。 -->
            <property name="desc" type="text" length="5000" column="`desc`"/>
        </class>
    </hibernate-mapping>

    我们从中可以看到User持久化类的属性desc的映射配置为:

    <property name="desc" type="text" length="5000" column="`desc`"/>

    思考一个问题:column属性为何要写成column=”`desc`”?可参考下面这段话: 
    在SQL语法中,表示符是指用于数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符(键盘~下面的字符)。 
    用更通俗易懂的话说就是:当列名与关键字冲突时,可以通过column属性指定一个其他的列名,或是使用反引号包围起来(不建议使用)。 
    现在我们编写单元测试来进行测试,在cn.itcast.c_hbm_property包下编写一个单元测试类——App.java。

    public class App {
        private static SessionFactory sessionFactory;
    
        static {
            sessionFactory = new Configuration() // 
                    .configure() // 读取配置文件
                    .addClass(User.class) //
                    .buildSessionFactory();
        }
    
        @Test
        public void testSave() throws Exception {
            // 创建对象实例
            User user = new User();
            user.setName("张三");
            user.setAge(20);
            user.setBirthday(new Date());
            user.setDesc("一大段的说明,此处省略5000字...");
    
            // 保存
            Session session = sessionFactory.openSession(); // 打开一个新的Session
            Transaction tx = session.beginTransaction(); // 开启事务
    
            session.save(user);
    
            tx.commit(); // 提交事务
            session.close(); // 关闭Session,释放资源
        }
    
        @Test
        public void testGet() throws Exception {
            Session session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();
    
            User user = (User) session.get(User.class, 1); // 获取?
            System.out.println(user.getId());
            System.out.println(user.getName());
            System.out.println(user.getDesc());
    
            tx.commit();
            session.close();
        }
    }

    运行testSave()方法,再去查看t_user表结构: 
     
    发现t_user表desc列的数据类型是longtext,而若是一定要让desc列的数据类型是text,也是有法子的,可以将

    <property name="desc" type="text" length="5000" column="`desc`"/>

    修改为:

    <property name="desc">
        <column name="desc_" length="5000" sql-type="text"></column>
    </property>

    这时再次运行testSave()方法,再去查看t_user表结构: 
     
    发现t_user表desc列的数据类型是text了,我们的目的达到了。虽说可以这样写,但是一般不建议这样写。 
    最后,我们在持久化类——User.java中加入一个字段:

    private byte[] photo; // 头像图片(二进制内容)

    映射文件中增加:

    <!-- 头像,二进制类型,最好指定长度 -->
    <property name="photo" type="binary" length="102400"></property>

    这时我们修改单元测试类——App.java的代码为:

    public class App {
        private static SessionFactory sessionFactory;
    
        static {
            sessionFactory = new Configuration() // 
                    .configure() // 读取配置文件
                    .addClass(User.class) //
                    .buildSessionFactory();
        }
    
        @Test
        public void testSave() throws Exception {
            // 读取图片文件
            InputStream in = new FileInputStream("c:/1.jpg");
            byte[] photo = new byte[in.available()];
            in.read(photo);
            in.close();
    
            // 创建对象实例
            User user = new User();
            user.setName("张三");
            user.setAge(20);
            user.setBirthday(new Date());
            user.setDesc("一大段的说明,此处省略5000字...");
            user.setPhoto(photo);
    
            // 保存
            Session session = sessionFactory.openSession(); // 打开一个新的Session
            Transaction tx = session.beginTransaction(); // 开启事务
    
            session.save(user);
    
            tx.commit(); // 提交事务
            session.close(); // 关闭Session,释放资源
        }
    
        @Test
        public void testGet() throws Exception {
            Session session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();
    
            User user = (User) session.get(User.class, 1); // 获取?
            System.out.println(user.getId());
            System.out.println(user.getName());
            System.out.println(user.getDesc());
            System.out.println(user.getPhoto());
    
            OutputStream out = new FileOutputStream("c:/copy.png"); 
            out.write(user.getPhoto());
            out.close();
    
            tx.commit();
            session.close();
        }
    }

    测试,通过,大发!!!

  • 相关阅读:
    idea 编译内存溢出
    版本兼容问题 用于数据存储的持久化
    java8 函数接口
    akka 的集群访问方式
    Akka Cluster Sharding
    讨厌的adb占用
    安卓编译 签名包
    linux 系统的 cache 过大,解决方案
    kotlin 简单处理 回调参数 加?
    HTML CSS + DIV实现局部布局
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6963150.html
Copyright © 2011-2022 走看看