组件映射
情况:
多个类中存在一些相同属性,将其抽取出来
与继承区别?
继承:
继承实在编译时刻静态定义的,较方便复用。但继承对子类暴露了其父类的实现细节,破坏了封装性;子类与父类有着较强的依赖关系,最终限制了复用
组合:
组合是通过获得对其他对象的引用而在运行时刻动态定义的。基于接口进行开发,所以实现上依赖性小
设计模式第二原则:
少用继承,多用组合
关系图:
具体实现
1、实体
<span style="font-size:18px;">contact:
/**
* 共有的联系方式值类
* @author gxq
*
*/
public class Contact {
//定义邮箱、地址、邮箱编号、联系方式
private String email;
private String address;
private String zipCode;
private String contactTel;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getContactTel() {
return contactTel;
}
public void setContactTel(String contactTel) {
this.contactTel = contactTel;
}
}
User:
/**
* 定义用户实体
* @author gxq
*
*/
public class User {
//id、姓名、联系方式
private int id;
private String name;
private Contact userContact;
public Contact getUserContact() {
return userContact;
}
public void setUserContact(Contact userContact) {
this.userContact = userContact;
}
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;
}
}
Employee:
/**
* 定以员工实体
* @author gxq
*
*/
public class Employee {
//id、姓名、联系方式
private int id;
private String name;
private Contact employeeContact;
public Contact getEmployeeContact() {
return employeeContact;
}
public void setEmployeeContact(Contact employeeContact) {
this.employeeContact = employeeContact;
}
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;
}
}</span>
2、映射文件
<span style="font-size:18px;">User:
<hibernate-mapping>
<class name="com.bjpowernode.component.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<component name="userContact">
<property name="email"></property>
<property name="address"></property>
<property name="zipCode"></property>
<property name="contactTel"></property>
</component>
</class>
</hibernate-mapping>
Employee:
<hibernate-mapping>
<class name="com.bjpowernode.component.Employee" table="t_employee">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<component name="employeeContact">
<property name="email"></property>
<property name="address"></property>
<property name="zipCode"></property>
<property name="contactTel"></property>
</component>
</class>
</hibernate-mapping>
</span>
3、配置文件
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">
<![CDATA[jdbc:mysql://localhost:3306/Hibernate?useUnicode=true&characterEncoding=utf8]]>
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="com/bjpowernode/component/User.hbm.xml"/>
<mapping resource="com/bjpowernode/component/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
4、封装好的工具类:HibernateUtils
/**
* 工具类(封装开启session和事务)
* @classname HibernateUtils
* @author 高晓青
* @date 2015-4-16 下午2:56:42
* @version hibernate
*/
public class HibernateUtils {
private static SessionFactory factory;
static{
try {
//默认读取的是hibernate.cfg.xml
Configuration cfg = new Configuration().configure();
//建立sessionFactory
factory = cfg.buildSessionFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
//开启session
public static Session getSession(){
return factory.openSession();
}
//关闭session
public static void closeSession(Session session){
//判断是否为空
if(session!=null){
//判断是否是打开状态再进行关闭
if(session.isOpen()){
session.close();
}
}
}
}
5、添加
public void testSaveComponent(){
Session session=null;
try {
//获取session,打开事务
session=HibernateUtils.getSession();
session.beginTransaction();
//定义User实体
User user=new User();
user.setName("小红");
//定义Contact实体
Contact contactUser=new Contact();
contactUser.setAddress("廊坊市");
contactUser.setContactTel("1324568923");
contactUser.setEmail("456876@qq.com");
contactUser.setZipCode("065000");
//将Contact实体加载到User实体中
user.setUserContact(contactUser);
session.save(user);
//定义Employee实体
Employee employee=new Employee();
employee.setName("张亮");
//定义Contact实体
Contact contactEmployee=new Contact();
contactEmployee.setAddress("石家庄市");
contactEmployee.setContactTel("18932623527");
contactEmployee.setEmail("2416876@qq.com");
contactEmployee.setZipCode("030000");
//将Contact实体加载到Employee实体中
employee.setEmployeeContact(contactEmployee);
session.save(employee);
//提交事务
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
6、查询
public void testLoad(){
Session session=null;
try {
//获取session,打开事务
session=HibernateUtils.getSession();
session.beginTransaction();
//根据用户id查询用户信息
User user=(User) session.load(User.class,1);
//打印用户姓名和地址
System.out.println(user.getName());
System.out.println(user.getUserContact().getAddress());
} catch (Exception e) {
e.printStackTrace();
}
}
特殊的组件映射:符合主键映射
情况:
把主键相关字段拿出单独一个类,这个类是由要求的:
- 必须实现序列化接口
- 覆盖equals和hashcode方法
关系图:
具体实现
1、实体
<span style="font-size:18px;">YearMonthPeriodPK:
/**
* 复合主键实体
*
* @author gxq
*
*/
public class YearMonthPeriodPK implements Serializable {
// 核算年份
private String ficalYear;
// 核算月份
private String ficalmonth;
public String getFicalYear() {
return ficalYear;
}
public void setFicalYear(String ficalYear) {
this.ficalYear = ficalYear;
}
public String getFicalmonth() {
return ficalmonth;
}
public void setFicalmonth(String ficalmonth) {
this.ficalmonth = ficalmonth;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((ficalYear == null) ? 0 : ficalYear.hashCode());
result = prime * result
+ ((ficalmonth == null) ? 0 : ficalmonth.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
YearMonthPeriodPK other = (YearMonthPeriodPK) obj;
if (ficalYear == null) {
if (other.ficalYear != null)
return false;
} else if (!ficalYear.equals(other.ficalYear))
return false;
if (ficalmonth == null) {
if (other.ficalmonth != null)
return false;
} else if (!ficalmonth.equals(other.ficalmonth))
return false;
return true;
}
}
YearPeriod:
/**
* 核算年实体
*
* @author gxq
*
*/
public class YearPeriod {
// 把主键当成一个属性
private YearMonthPeriodPK yearMonthPeriodPK;
// 开始时间
private Date beginDate;
// 结束时间
private Date endDate;
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public YearMonthPeriodPK getYearMonthPeriodPK() {
return yearMonthPeriodPK;
}
public void setYearMonthPeriodPK(YearMonthPeriodPK yearMonthPeriodPK) {
this.yearMonthPeriodPK = yearMonthPeriodPK;
}
}
MonthPeriod:
/**
* 月核算实体
* @author gxq
*
*/
public class MonthPeriod {
//把主键当成一个属性
private YearMonthPeriodPK yearMonthPeriodPK;
//开始时间
private Date beginDate;
//结束时间
private Date endDate;
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public YearMonthPeriodPK getYearMonthPeriodPK() {
return yearMonthPeriodPK;
}
public void setYearMonthPeriodPK(YearMonthPeriodPK yearMonthPeriodPK) {
this.yearMonthPeriodPK = yearMonthPeriodPK;
}
}
</span>
2、映射文件
YearPeriod:
<hibernate-mapping>
<class name="com.bjpowernode.component.YearPeriod" table="t_yearPeriod">
//复合主键
<composite-id name="yearMonthPeriod">
<key-property name="ficalYear"></key-property>
<key-property name="ficalmonth"></key-property>
</composite-id>
<property name="beginDate" type="date" />
<property name="endDate" type="date" />
</class>
</hibernate-mapping>
MonthPeriod:
<hibernate-mapping>
<class name="com.bjpowernode.component.MonthPeriod" table="t_monthPeriod">
//复合主键
<composite-id name="yearMonthPeriodPK">
<key-property name="ficalYear"></key-property>
<key-property name="ficalmonth"></key-property>
</composite-id>
<property name="beginDate" type="date"/>
<property name="endDate" type="date"/>
</class>
</hibernate-mapping>
3、配置文件
同上
4、封装好的工具类:HibernateUtils
同上
5、添加
<span style="font-size:18px;">public void testComposite() {
Session session = null;
try {
// 获取session,打开事务
session = HibernateUtils.getSession();
session.beginTransaction();
//实例年核算期
YearPeriod yearPeriod=new YearPeriod();
//构造复合主键对象
YearMonthPeriodPK yearMonthPeriodPK=new YearMonthPeriodPK();
yearMonthPeriodPK.setFicalmonth("6");
yearMonthPeriodPK.setFicalYear("2016");
yearPeriod.setYearMonthPeriodPK(yearMonthPeriodPK);
yearPeriod.setBeginDate(new Date());
yearPeriod.setEndDate(new Date());
//保存年核算期
session.save(yearPeriod);
//实例年核算期
MonthPeriod monthPeriod=new MonthPeriod();
//构造复合主键对象
YearMonthPeriodPK yearMonthPeriodPKMonth=new YearMonthPeriodPK();
yearMonthPeriodPKMonth.setFicalmonth("5");
yearMonthPeriodPKMonth.setFicalYear("2015");
monthPeriod.setYearMonthPeriodPK(yearMonthPeriodPKMonth);
monthPeriod.setBeginDate(new Date());
monthPeriod.setEndDate(new Date());
//保存月核算期
session.save(monthPeriod);
// 提交事务
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
</span>
6、查询
public void testComposite(){
Session session=null;
try {
session=HibernateUtils.getSession();
session.beginTransaction();
//构造复合主键对象
YearMonthPeriodPK yearMonthPeriodPK=new YearMonthPeriodPK();
yearMonthPeriodPK.setFicalmonth("6");
yearMonthPeriodPK.setFicalYear("2016");
YearPeriod yearPeriod=(YearPeriod) session.load(YearPeriod.class,yearMonthPeriodPK);
System.out.println(yearPeriod.getBeginDate());
} catch (Exception e) {
e.printStackTrace();
}
}