一.Hibernate测试代码
直接上代码,具体解释见代码注释
必不可少之Hibernate主配置文件hibernate.cfg.xml(上面的代码结构图里没加上)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///my?useUnicode=true&characterEncoding=utf-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.connection.isolation">4</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="dialect"></property>
<mapping resource="cjx/OneAndManyTable/ContactPerson.hbm.xml" />
<mapping resource="cjx/OneAndManyTable/Customerl.hbm.xml" />
</session-factory>
</hibernate-configuration>
自己写的工具类HibernateUtil.java(上面的代码结构图里没加上)
public class HibernateUtil {
// 用于测试的主函数
// public static void main(String[] args) {
// System.out.println(HibernateUtil.openSession());
// }
private static SessionFactory sf;
static{
//1.创建,调用空参构造
Configuration conf = new Configuration().configure();
//2.根据配置信息,创建 SessionFactory对象
sf = conf.buildSessionFactory();
}
//获得session => 获得全新session
public static Session openSession(){
Session session = sf.openSession();
return session;
}
//获得session => 获得与线程绑定的session
public static Session getCurrentSession(){
Session session = sf.getCurrentSession();
return session;
}
}
Customer.java
public class Customer {//客户实体
private String id;
private String name;
//使用set集合表达一对多关系
private Set<ContactPerson> contact=new HashSet<ContactPerson>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<ContactPerson> getContact() {
return contact;
}
public void setContact(Set<ContactPerson> contact) {
this.contact = contact;
}
}
Customerl.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cjx.OneAndManyTable">
<class table="customer" name="cjx.OneAndManyTable.Customer">
<id name="id">
<generator class="uuid"></generator>
</id>
<property name="name" />
<!-- 在配置文件中配置一对多,因为Customer实体类中用的set集合,这里就用set元素
name:集合属性名,Customer实体类中的一对多属性
column:外键列名,外键的列名
class:关联的实体类的完整类名
-->
<!-- 级联操作:cascade 作用:可以简化操作,减少代码量,但可能造成误操作
save-update:级联保存更新
delete:级联删除
all:级联保存更新删除
配置一对多时,操作一表时会自动关联多表
例如:操作Customer时会自动关联操作ContactPerson
-->
<!-- inverse属性:用于配置关系是否维护
true:不维护关系(inverse是反转的意思)
false(默认值):维护关系
inverse属性作用:性能优化,可以减少Hibernate生成的语句量
原则:必须有一方维护关系。一对多关系中只能是一的一方放弃维护关系
-->
<set name="contact" cascade="save-update" inverse="true" >
<key column="cpid"></key>
<one-to-many class="cjx.OneAndManyTable.ContactPerson" /><!--指定为一对多,并指定对应的实体类-->
</set>
<!-- 扩展:其他属性
lazy属性:决定是否延迟加载,懒加载
true(默认值):延迟加载
false:立即加载
extra:极其懒惰
fetch属性:决定加载策略,使用什么类型的SQL语句加载集合数据
select(默认值):单表查询加载
join:多表查询加载
subselect:子查询加载
batch-size:批量抓取
-->
</class>
</hibernate-mapping>
ContactPerson.java
public class ContactPerson {//客户拥有的联系人实体
//一个客户拥有多个联系人
private String id;
private String cpid;//外键
private String name;
private String age;
private String sex;
private String qq;
private String email;
private String address;
private Customer customer;//表达多对一关系
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCpid() {
return cpid;
}
public void setCpid(String cpid) {
this.cpid = cpid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getQq() {
return qq;
}
public void setQq(String qq) {
this.qq = qq;
}
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 Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
ContactPerson.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cjx.OneAndManyTable">
<class table="contactperson" name="cjx.OneAndManyTable.ContactPerson">
<id name="id">
<generator class="uuid"></generator>
</id>
<property name="cpid" />
<property name="name" />
<property name="age" />
<property name="sex" />
<property name="qq" />
<property name="email" />
<property name="address" />
<!-- 多对一 ,在配置文件中配置
name:引用属性名,ContactPerson实体类中多对一属性
column:外键列名,ContactPerson实体类中外键的列名
class:关联的实体类的完整类名
-->
<!-- 级联操作:cascade 作用:可以简化操作,减少代码量,但可能造成误操作
save-update:级联保存更新
delete:级联删除
all:级联保存更新删除
配置多对一时,操作多表时会自动关联一表
例如:操作ContactPerson时会自动关联操作Customer
-->
<!-- inverse属性:在此处不能放弃维护关系,外键字段在多的一方,不能放弃-->
<many-to-one name="customer" column="cpid" cascade="save-update"
class="cjx.OneAndManyTable.Customer"
insert="false" update="false"></many-to-one>
</class>
</hibernate-mapping>
测试代码OneAndManyTable.java
public class OneAndManyTable {//一对多和多对一操作
@Test
//保存客户和联系人
public void funone(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//创建数据
Customer c=new Customer();
c.setName("客户A");
ContactPerson cp1=new ContactPerson();
cp1.setName("客户A的联系人A");
cp1.setQq("123456");
ContactPerson cp2=new ContactPerson();
cp2.setName("客户A的联系人B");
cp2.setAge("18");
//表达一对多,客户下有多个联系人
// c.getContact().add(cp1);//如果Customer放弃维护关系,则维护关系的代码可以不写
// c.getContact().add(cp2);//如果Customer放弃维护关系,则维护关系的代码可以不写
//表达多对一,联系人属于哪个客户
cp1.setCustomer(c);
cp2.setCustomer(c);
//保存
session.save(c);
session.save(cp1);//配置级联操作后,此步可省
session.save(cp2);//配置级联操作后,此步可省
/*注意:如果Customer放弃维护关系,且维护关系的代码不写
* 级联操作将不会起作用,ContactPerson不会被保存
* 由此可知级联操作由维护关系的代码决定
*/
tx.commit();
session.close();
}
@Test
//删除客户的联系人
public void funtwo(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
Customer customer = session.get(Customer.class, "297eaf72634a258f01634a2596b40000");
// ContactPerson contactPerson = session.get(ContactPerson.class, "297eaf72634a258f01634a2596c30001");
// customer.getContact().remove(contactPerson);
// contactPerson.setCustomer(null);
//配置了级联删除后,上面的三行代码替换为下面的一行代码
session.delete(customer);
tx.commit();
session.close();
}
//删除客户,此处不用于测试
public void funthree(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
Customer customer = session.get(Customer.class, "297eaf72634a258f01634a2596c30001");
/*由于Customer与ContactPerson表相关联,所以可能不能直接删除
* 方案一:解除外键
* inverse="true" 外键会置为空
* 方案二:级联删除
* inverse="true"
* cascade="delete"
*/
session.delete(customer);
tx.commit();
session.close();
}
}