在第一部分中我给大家介绍了一下,hibernate开发常用的注解也是最基本的注解,比如@Entity、@Table等注解以及这些注解的主要属性(如果有读者想看一下第一部分的介绍请链接这个地址:http://blog.csdn.net/cdw2328/article/details/71425184)。下面我就给大家继续第一部分的内容介绍一下hibernate的嵌入式注解,首先我先说一下什么是嵌入式。
嵌入式:嵌入式就是把某些事物镶嵌到另一个事物中,而保证另一个事物的完整性不会遭到破坏,使其功能更加的完善。我今天给大家说的嵌入式注解基本上符合这样的一个描述。接下来我要向大家介绍今天关于嵌入式注解的hibernate注解:@Embeddable、@Embedded、@AttributeOverrides、@AttributeOverride,今天的介绍这四个注解我还是以逐步深入的思路来进行介绍。
第二部分的介绍还是以第一部分所创建的Web Project项目为基础项目来介绍。
这一部分我添加了三个Entity分别是User、Address、Parcel这三个实体类。在hibernate中实现自定义类型,只要实现UserType接口即可或者以Component的形式提供.JPA的@Embedded有点类似,通过此注释可以在你的Entity中使用一般的Java对象,此对象需要用@Embeddable标注。那么我们就以User、Address、Parcel这个实体类给大家举个例子:
一个实例化的User要在国外的电商网站上购买了一件物品,那么电商的卖家要向把货物准确无误发送的客户的手里,而客户要看到货物的订单信息这两者之间需要什么可以实现上述的要求呢?其实很简单的,我们在User实体对象中的属性中添加客户的基本属性、地址的基本属性和包裹的基本属性就可以了。就像下图一样:
我们完全可以把地址和包裹的属性都写到User中,但这样写会有什么的问题呢?如果我以后还要添加包裹的其他属性会很麻烦的,还有如果还有别的对象要用的Parcel对象里的属性,我把属性都写到User中别的对象引用起来是不是会比较的麻烦呢。Address也是这个道理。所以这里就把关于地址的属性全部重新划分到另一个新的对象中,把关于包裹的属性的重新的划分到另一个对象中。这样我的实体类的对象中就多出了两个实体类的对象Address和Parcel。如下图:
现在就把关于地址的属性全部写到Address对象中,把关于包裹的属性全部写到Parcel中。这样就在一定程度上减低的了代码的耦合度。
下面就是分离后的User对象、Address对象、Parcel对象和他们的属性
User对象:
Address对象:
parcel对象:
最后把Address对象和parcel对象加入User中即可:
然后显示的生成无参的构造器和实现Serializable接口,这两个必须要有。其他的类似像get和set方法等自己生成即可;
接下来我就重点介绍这四个接口:
我们先看一下以上次介绍的第一部分中的仅仅加上@Entity、@Table看一下在User对象映射关系在数据库中生成的是什么:
这里我生成了有参的构造器,在构造器中我添加了Address对象和parcel对象。
下面是我的测试代码:
import java.util.UUID;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import com.bd.cdw.pojo.Address;
import com.bd.cdw.pojo.HibernateAnnotation;
import com.bd.cdw.pojo.Parcel;
import com.bd.cdw.pojo.User;
/**
*
*<p>Title:测试hibernate注解的映射表关系</p>
*<p>Description:</p>
*<p>Company:www.bd.com</p>
*
* @author 陈大伟
* @date 2017年5月8日上午10:43:39
* @version 1.4
*/
public class TestHibernatePojoAnnotationMapper
{
public static void main(String[] args)
{
Configuration configuration=null;
ServiceRegistry serviceRegistry=null;
SessionFactory sessionFactory=null;
Session session=null;
try {
configuration=new Configuration().configure();
serviceRegistry=
new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory=configuration.buildSessionFactory(serviceRegistry);
session=sessionFactory.openSession();
session.beginTransaction();
Address address=new Address("中国","北京","昌平区","天通苑","立水桥","鲍家街58号");
Parcel parcel=new Parcel(UUID.randomUUID().toString(),"梦芭莎");
User user=new User(null,"柳岩","123456",address,parcel);
User user1=new User(null,"柳岩","123456");
session.save(user);
session.getTransaction().commit();
session.close();
} catch (Exception e) {
e.getMessage();
}
finally
{
session.close();
sessionFactory.close();
}
}
}
随着介绍的逐步深入我就不再写全篇的测试代码,只对中间的进行修改.我运行这个main方法看一下数据库中生成的是什么?
可以看到数据中生成的表只是除了User对象自身的属性外把Address对象和Parcel对象当成了User对象的一个属性进行了创建,Address对象和Parcel对象的属性并没有添加到数据库中,这样就和我的初衷相违背了。这时要解决这种问题我们就要用的到一个嵌入式的注解:@Embeddable、@Embedded。这两个注解乍一看好像啊,这两个注解有什么作用呢?怎么用呢?
@Embeddable注释,表示此类可以被嵌入到某个entity中,这个注释加到那个类上就代表那个类是嵌入类。我们就在Address类的上面加上这个注解看一下生成数据库中的表(这里没有给Parcel加这个注解并且Address对象中没有Parcel对象在User中也没有Parcel对象):
数据库中生成的表:
java的测试代码:
session.beginTransaction();
Address address=new Address("中国","北京","昌平区","天通苑","立水桥","鲍家街58号");
User user2=new User(null,"柳岩","123456",address);
session.save(user2);
session.getTransaction().commit();
可以看到这里已经把Address这个对象嵌入进了User中。接下了我们继续嵌入parcel对象,在User对象中添加私有化parcel对象,生成parcel对象在User对象中的有参构造函数和get和set方法。(不在Address对象中添加),在parcel类的上面添加@Embeddable
User对象:
在parcel类上面添加@Embeddable注解:
测试代码:
session.beginTransaction();
Address address=new Address("中国","北京","昌平区","天通苑","立水桥","鲍家街58号");
Parcel parcel=new Parcel(UUID.randomUUID().toString(),"梦芭莎");
User user=new User(null,"柳岩","123456",address,parcel);
session.save(user);
session.getTransaction().commit();
数据库中生成的表:
现在可以看到现在Address对象和parcel对象都完成了嵌入。
下面我继续介绍@Embedded、@AttributeOverrides、@AttributeOverride
@Embedded是注释对象属性的加到对象的属性上,表示该属性的类是嵌入类.
@AttributeOverrides由多个@AttributeOverride注释组成,每个@AttributeOverride表示属性的映射
@AttributeOverride注释来指定某个对象的属性与数据库中表的指定字段进行映射.
假设我现在需要对parcel对象中的属性: parcelId parcelName;在生成数据表时,嵌入指定在数据库中的字段名称。就要用到这三个注解:
一.在User对象中生成parcel对象的get和set方法。在生成的parcel对象的get方法上使用这三个注解:
@AttributeOverride注释应注意以下几方面的问题:
name属性表示嵌入式类中的属性原有的名称。
column属性表示,所嵌入的实体类中对列的重新定义(可以理解为对原本数据库映射的字段的名称修改为指定的名称),其中@Column标记表示的意义声明了属性到列的映射;说白了以上图为例,我不想在生成数据库表时让parcel对象的两个字段映射为parcelId parcelName,我先把它变成另外的两个名称比如(bornPparcelId和bornParcelname)其他的都没有进行改动,测试类的代码还是上面的代码。
下面我们看一下数据库的表:
下面我们就在Address对象中修改他的字段名称.目的:把关于Address中的所有属性名称指定c_XXX的。如c_city的,要求不改变Address对象中的属性名称,利用上述的三个注解进行重新指定数据库的关于Address对象的字段名称。
User对象中在getAddress上面使用:
Address对象中的属性不改变:
最后生成的数据库表:
至此关于hibernate嵌入式注解就完了,由于水有限有不正之处请各位读者敬请指正和谅解!第三部分是表与表之间的关系注解在下一次介绍中继续。