Hibernate(四)

观察:二级缓存的作用
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo10 {
public static void main(String[] args) {
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
Person per = null;
per = (Person) session.get(Person.class, 1);
session.close();
session = new Configuration().configure().buildSessionFactory()
.openSession();
per = (Person) session.get(Person.class, 1);
session.close() ;
}
}
可以发现,以上的代码只执行了一次的查询语句,虽然是两个session,但是可以共享缓存的数据。
当然,也可以清空掉全部的缓存,之后重新查询。
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo11 {
public static void main(String[] args) {
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
Person per = null;
per = (Person) session.get(Person.class, 1);
new Configuration().configure().buildSessionFactory().evict(per.getClass());
session.close();
session = new Configuration().configure().buildSessionFactory()
.openSession();
per = (Person) session.get(Person.class, 1);
session.close();
}
}
在SessionFactory中只能一个个的删除被缓存的对象,不能全部清空缓存内容。
除了以上的配置之外,缓存也可以直接在hibernate.cfg.xml文件中进行配置的。
<class-cache class="org.lxh.hibernate.demo06.Person"
usage="read-only" />
以后直接修改hibernate.cfg.xml就可以达到缓存的配置。
3.4.3、缓存交互
缓存交互指的是一级缓存可以二级缓存进行数据的交换。
主要使用Session对象中的:public void setCacheMode(CacheMode cacheMode)
在设置交互的时候,也存在着以下的几种交互模式:
• CacheMode.NORMAL:从二级缓存中读、写数据。
• CacheMode.GET:从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。
• CacheMode.PUT:仅向二级缓存写数据,但不从二级缓存中读数据。
•CacheMode.REFRESH:仅向二级缓存写数据,但不从二级缓存中读数据。通过 hibernate.cache.use_minimal_puts的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo12 {
public static void main(String[] args) {
Session session1 = new Configuration().configure().buildSessionFactory()
.openSession();
Person per = null;
// 此时让一级缓存中的内容不保存在二级缓存里去
session1.setCacheMode(CacheMode.GET) ;
per = (Person) session1.get(Person.class, 1);
session1.close();
Session session2 = new Configuration().configure().buildSessionFactory()
.openSession();
per = (Person) session2.get(Person.class, 1);
session2.close();
}
}
此时,程序发出了两条语句,因为第一个session中并没有把查询的内容放到缓存之中。
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo13 {
public static void main(String[] args) {
Session session1 = new Configuration().configure()
.buildSessionFactory().openSession();
Person per = null;
per = (Person) session1.get(Person.class, 1);
session1.close();
Session session2 = new Configuration().configure()
.buildSessionFactory().openSession();
// 不从二级缓存中读,但是写
session2.setCacheMode(CacheMode.PUT);
per = (Person) session2.get(Person.class, 1);
session2.close();
Session session3 = new Configuration().configure()
.buildSessionFactory().openSession();
// 不从二级缓存中写,但是读
session3.setCacheMode(CacheMode.GET);
per = (Person) session3.get(Person.class, 1);
session3.close();
}
}
3.4.4、查询缓存
现在有如下程序:
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo14 {
public static void main(String[] args) {
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
for (int x = 0; x < 100; x++) {
Query q = session.createQuery("FROM Person p") ;
q.list() ;
}
session.close();
}
}
程序运行后,可以发现发出100次的重复的查询语句,此种做法肯定不可取,所以此时就必须配置查询缓存,如果要想配置一个查询缓存,则首先必须在hibernate.cfg.xml文件中进行配置。添加属性:
hibernate.cfg.xml:
<property name="cache.use_query_cache">true</property>
以上的属性表示启动了查询缓存,但是光有此配置是不够的,还需要在查询上指定查询必须被缓存。在Query接口上有一个:
q.setCacheable(true) ;
表示启动查询缓存。执行之后,发现只发出了一条查询语句,所以此语句被缓存了。
缓存直接与程序的性能有关,尤其是在使用大数据量插入或查询的时候尤其重要。
3.5、容器映射技术(重点)
所谓的容器映射实际上就是对多张表的关系映射,但是对于整个程序来说,只有一个配置文件(*.hbm.xml),但是一个文件可以同时操作多张表。
容器映射主要是分为三种:
• Set映射:
• List映射:
• Map映射:
3.5.1、Set映射(绝对重点)
Set集合中肯定不能存放重复的元素。
现在表示出如下的一种关系:一个人有多个email地址。肯定要设计出两张表:
DROP TABLE email ;
DROP TABLE person ;
CREATE TABLE person(
pid INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
name VARCHAR(50) NOT NULL ,
age INT NOT NULL
) ;
CREATE TABLE email(
pid INT ,
mail VARCHAR(200) NOT NULL ,
FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE
) ;
Person是主表,email是从表,在从表中除了ID之外只有一个字段,此时就可以使用容器映射。在POJO类中必须明确的表示出此种关系:
Person.java:
import java.util.Set;
import java.util.TreeSet;
public class Person {
private int pid ;
private String name ;
private int age ;
private Set mails ;
public Person(){
this.mails = new TreeSet() ;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Set getMails() {
return mails;
}
public void setMails(Set mails) {
this.mails = mails;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
}
一个人有多个email地址。但是此时在POJO类中的关系必须在映射文件之中进行明显的配置,修改Person.hbm.xml文件。
Person.hbm.xml:
<hibernate-mapping>
<class name="org.lxh.hibernate.demo07.Person" table="person"
catalog="demo">
<id name="pid" type="java.lang.Integer">
<column name="pid" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="50" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<set name="mails"  表示使用了一个Set集合,name表示Person类中的属性名称
table="email">  表示此集合对应的表
<key column="pid" />  主表与子表之间的关联字段
<element type="java.lang.String"  表示集合中的每一个元素
column="mail"></element>  每一个元素的值都对应着mail字段
</set>
</class>
</hibernate-mapping>
测试代码:
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo07 {
private Session session = null;
public TestDemo07() {
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
public void doCreate() {
Person per = new Person();
per.setName("张三");
per.setAge(30);
per.getMails().add("aa@aa.com");
per.getMails().add("aa@aa.com");
per.getMails().add("ab@aa.com");
per.getMails().add("ac@aa.com");
this.session.save(per);
this.session.beginTransaction().commit();
this.session.close();
}
public static void main(String[] args) {
new TestDemo07().doCreate();
}
}
程序代码执行了4条SQL语句,第一条表示的是向person表中插入数据,其他三条表示向email表中插入数据。
观察查询:
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo08 {
private Session session = null;
public TestDemo08() {
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
public void find() {
String hql = "FROM Person p WHERE p.pid=?";
Query q = this.session.createQuery(hql);
q.setInteger(0, 1);
Person p = (Person) q.uniqueResult(); // 查询的只是person中的表
p.getMails().size(); // 当用到的时候再发出查询语句
this.session.close();
}
public static void main(String[] args) {
new TestDemo08().find();
}
}
对于集合的数据,因为一般其内容较多,所以在Hibernate中就默认的设置其为延迟加载,当需要数据的时候再进行查询。
p.getMails().size();
对于延迟加载来说,一定要在session关闭前,将内容查询出来,否则会出现session被关闭的异常。
可以直接通过修改*.hbm.xml文件将延迟加载关闭。
<set name="mails"
table="email" lazy="false">
<key column="pid" />
<element type="java.lang.String"
column="mail"></element>
</set>
之后再进行查询,同时将集合的操作取消:
public void find() {
String hql = "FROM Person p WHERE p.pid=?";
Query q = this.session.createQuery(hql);
q.setInteger(0, 1);
Person p = (Person) q.uniqueResult(); // 查询的只是person中的表
this.session.close();
}
程序发出了两条语句,不管是否使用全部查询出来。
对于Set映射中,也可以修改数据。
public void update() {
Person per = new Person();
per.setPid(1) ;
per.setName("李四");
per.setAge(31);
per.getMails().add("Xx@aa.com");
per.getMails().add("UU@aa.com");
per.getMails().add("ab@aa.com");
per.getMails().add("ac@aa.com");
this.session.update(per);
this.session.beginTransaction().commit();
this.session.close();
}
以上的Person对象是一个新的对象,此时观察执行的SQL语句:
Hibernate: update demo.person set name=?, age=? where pid=?
Hibernate: delete from email where pid=?
Hibernate: insert into email (pid, mail) values (?, ?)
Hibernate: insert into email (pid, mail) values (?, ?)
Hibernate: insert into email (pid, mail) values (?, ?)
Hibernate: insert into email (pid, mail) values (?, ?)
以上的SQL语句表示,先更新主表,之后删除全部子表中的相关数据,重新插入,因为插入的内容是一个新的实体对象。
但是,如果此时,先进行查询之后再更新呢?
public void update() {
Person per = (Person)this.session.get(Person.class, 1) ;
per.setPid(1) ;
per.setName("张三");
per.setAge(20);
per.getMails().add("Xx@aa.com");
per.getMails().add("UU@aa.com");
per.getMails().add("BB@aa.com");
per.getMails().add("CC@aa.com");
this.session.update(per);
this.session.beginTransaction().commit();
this.session.close();
}
现在的内容是先查询之后再更新的,观察执行的SQL语句:
Hibernate: select person0_.pid as pid0_0_, person0_.name as name0_0_, person0_.age as age0_0_ from demo.person person0_ where person0_.pid=?
Hibernate: select mails0_.pid as pid0_, mails0_.mail as mail0_ from email mails0_ where mails0_.pid=?  因为没有设置延迟加载,所以一起查询了
Hibernate: update demo.person set name=?, age=? where pid=?
Hibernate: insert into email (pid, mail) values (?, ?)
Hibernate: insert into email (pid, mail) values (?, ?)
因为有两个新的email地址,所以现在向表中重新插入新的内容。
因为在Hibernate中要维持一个对象的状态。
3.5.2、List映射
List映射表示的是允许有重复的元素,例如一个人有多本书,书的名字是有可能重复的。
DROP TABLE book ;
DROP TABLE person ;
CREATE TABLE person(
pid INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
name VARCHAR(50) NOT NULL ,
age INT NOT NULL
) ;
CREATE TABLE book(
pid INT ,
title VARCHAR(200) NOT NULL ,  书的名字全部一样
num INT NOT NULL ,  区分不同的书
FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE
) ;
Person.java:
import java.util.ArrayList;
import java.util.List;
public class Person {
private int pid ;
private String name ;
private int age ;
private List books ;
public Person(){
this.books = new ArrayList() ;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public List getBooks() {
return books;
}
public void setBooks(List books) {
this.books = books;
}
}
Person.hbm.xml:
<hibernate-mapping>
<class name="org.lxh.hibernate.demo08.Person" table="person" catalog="demo">
<id name="pid" type="java.lang.Integer">
<column name="pid" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="50" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<list name="books"  配置List集合
table="book">  对应的表
<key column="pid"></key>  关联键
<index column="num"></index>  索引值,自动处理
<element type="java.lang.String"
column="title"></element>
</list>
</class>
</hibernate-mapping>
测试:
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class TestDemo07 {
private Session session = null;
public TestDemo07() {
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
public void doCreate() {
Person per = new Person();
per.setName("张三");
per.setAge(30);
per.getBooks().add("C++") ;
per.getBooks().add("C++") ;
per.getBooks().add("C++") ;
per.getBooks().add("JAVA") ;
per.getBooks().add("JAVA") ;
per.getBooks().add("JAVA") ;
per.getBooks().add("JAVA") ;
this.session.save(per);
this.session.beginTransaction().commit();
this.session.close();
}
public static void main(String[] args) {
new TestDemo07().doCreate();
}
}
3.5.3、Map映射
Map映射就是存放一对key  value的关联。
例如:一个人可以有多个项目,每个项目有项目的名称及描述。
DROP TABLE project ;
DROP TABLE person ;
CREATE TABLE person(
pid INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
name VARCHAR(50) NOT NULL ,
age INT NOT NULL
) ;
CREATE TABLE project(
pid INT ,
name VARCHAR(200) NOT NULL ,
descr VARCHAR(60) NOT NULL ,
FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE
) ;
子表中存在着一对关联的关系:key  value。
此时,就只能在POJO类中完成Map映射了。
Person.java:
import java.util.HashMap;
import java.util.Map;
public class Person {
private int pid;
private String name;
private int age;
private Map projects;
public Person() {
this.projects = new HashMap();
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public Map getProjects() {
return projects;
}
public void setProjects(Map projects) {
this.projects = projects;
}
}
在映射文件之中,表示出此种关系:
<hibernate-mapping>
<class name="org.lxh.hibernate.demo09.Person" table="person"
catalog="demo">
<id name="pid" type="java.lang.Integer">
<column name="pid" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="50" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<map name="projects" table="project">
<key column="pid"></key>
<map-key type="java.lang.String"  配置Map中的key
column="name"></map-key>
<element type="java.lang.String"  配置Map中的value
column="descr"></element>
</map>
</class>
</hibernate-mapping>
测试:
public void doCreate() {
Person per = new Person();
per.setName("张三");
per.setAge(30);
per.getProjects().put("JAVA", "网络登陆系统") ;
per.getProjects().put("J2EE", "ERP系统") ;
this.session.save(per);
this.session.beginTransaction().commit();
this.session.close();
}
三种容器映射技术之中,都是两张表的,但是对于Set映射来说,被关联的字表出了主键之外只能有一个字段。
如果一个被关联表中需要有更多的字段,则只能使用数据关联技术。
3.6、数据关联技术(重点中的重点)
数据关联指的是以下三种关联:
• 一对一关联
• 一对多关联
• 多对多关联
3.6.1、一对一关联
例如:一个人有一张护照。应该需要两张表,一张是人员表,另外一张是护照表:
DROP TABLE passport ;
DROP TABLE person ;
CREATE TABLE person(
pid INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
name VARCHAR(50) NOT NULL ,
age INT NOT NULL
) ;
CREATE TABLE passport(
pid INT ,
serial VARCHAR(30) UNIQUE NOT NULL ,
expiry INT ,
FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE
) ;
此时被关联表中存在多个字段,所以此时在建立POJO类的时候肯定要建立两个POJO类。
Person中应该包含Passport属性,而Passport类中要包含Person的属性。
Person.java:
public class Person {
private int pid ;
private String name ;
private int age ;
private Passport passport ;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Passport getPassport() {
return passport;
}
public void setPassport(Passport passport) {
this.passport = passport;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
}
Passport.java:
public class Passport {
private int pid ;
private String serial ;
private int expiry ;
private Person person ;
public int getExpiry() {
return expiry;
}
public void setExpiry(int expiry) {
this.expiry = expiry;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
}
但是两个类中的关联关系如果要想正确的时候,则必须在映射文件之中进行配置。
Person.hbm.xml:
<hibernate-mapping>
<class name="org.lxh.hibernate.demo10.Person" table="person"
catalog="demo">
<id name="pid" type="java.lang.Integer">
<column name="pid" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="50" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<one-to-one name="passport"
class="org.lxh.hibernate.demo10.Passport">
</one-to-one>
</class>
</hibernate-mapping>
Passport.hbm.xml:
在护照表中,其编号由Person决定的,而且配置了外键的关系。
<hibernate-mapping>
<class name="org.lxh.hibernate.demo10.Passport" table="passport"
catalog="demo">
<id name="pid" column="pid" type="java.lang.Integer">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="serial" type="java.lang.String"
column="serial">
</property>
<property name="expiry" type="java.lang.Integer"
column="expiry">
</property>
<one-to-one name="person"
class="org.lxh.hibernate.demo10.Person">
</one-to-one>
</class>
</hibernate-mapping>
编写测试:
public void doCreate() {
Person per = new Person();
per.setName("张三");
per.setAge(30);
Passport pass = new Passport() ;
pass.setSerial("1111111111111111") ;
pass.setExpiry(30) ;
per.setPassport(pass) ;
pass.setPerson(per) ;
this.session.save(per);
this.session.beginTransaction().commit();
this.session.close();
}
程序执行后,只插入了一条SQL语句。
因为程序中没有配置级联关系,所以在插入人的时候虽然在类中配置好了人与护照的一对一关系,但是程序现在依然不会插入护照的信息。
<one-to-one name="passport"
class="org.lxh.hibernate.demo10.Passport" cascade="all">
</one-to-one>
执行查询观察结果:
public void find1() {
String hql = "FROM Person p WHERE p.pid=1";
Person per = (Person) this.session.createQuery(hql).uniqueResult();
System.out.println(per.getName());
System.out.println(per.getPassport().getSerial());
this.session.close();
}
public void find2() {
Person per = (Person) this.session.get(Person.class, 1);
System.out.println(per.getName());
System.out.println(per.getPassport().getSerial());
this.session.close();
}
更新操作:
public void doUpdate() {
Person per = new Person();
per.setPid(1) ;
per.setName("李四");
per.setAge(30);
Passport pass = new Passport() ;
pass.setSerial("222222222") ;
pass.setExpiry(32) ;
per.setPassport(pass) ;
pass.setPerson(per) ;
this.session.update(per);
this.session.beginTransaction().commit();
this.session.close();
}
以上是一个新的实体,进行更新操作。
执行的SQL语句:
Hibernate: insert into demo.passport (serial, expiry, pid) values (?, ?, ?)
Hibernate: update demo.person set name=?, age=? where pid=?
出现了两条,导致了程序更新错误。
public void doUpdate2() {
Person per = new Person();
per.setPid(1) ;
per.setName("李四");
per.setAge(30);
this.session.update(per);
this.session.beginTransaction().commit();
this.session.close();
}
更新的时候如果配置好了关联关系,则有可能会执行插入新记录的操作。
public void doUpdate3() {
Person per = (Person)this.session.get(Person.class, 1) ;
per.setName("李四");
per.setAge(30);
per.getPassport().setSerial("222222222") ;
per.getPassport().setExpiry(32) ;
this.session.update(per);
this.session.beginTransaction().commit();
this.session.close();
}
执行的SQL语句:
Hibernate: update demo.passport set serial=?, expiry=? where pid=?
Hibernate: update demo.person set name=?, age=? where pid=?
因为是先查询出来的实体,所以保存了对象的状态,更新的时候就不会再进行重新插入了。
但是以上的操作都是使用update方法完成的,本身不建议这样使用,最好使用HQL中的update方法。
3.6.2、一对多关联(重点)
一个部门有多个雇员:
• 部门表
• 雇员表
DROP TABLE emp ;
DROP TABLE dept ;
CREATE TABLE dept(
deptno INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
dname VARCHAR(50) NOT NULL ,
loc VARCHAR(50) NOT NULL
);
CREATE TABLE emp(
empno INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
ename VARCHAR(50) NOT NULL ,
saly FLOAT NOT NULL ,
hiredate DATE ,
deptno INT ,
FOREIGN KEY(deptno) REFERENCES dept(deptno)
) ;
此时,就可以返回MyEcplise中最好用的一个功能,会自动帮用户建立好关联关系,会自动将POJO类配置好关系。
在插入数据的时候必须配置好关联关系:
public void doCreate() {
Dept d = new Dept() ;
d.setDname("技术部") ;
d.setLoc("北京") ;
Emp e = null ;
e = new Emp() ;
e.setEname("张三") ;
e.setSaly(800.0f) ;
e.setHiredate(new Date()) ;
e.setDept(d) ;
d.getEmps().add(e) ;
e = new Emp() ;
e.setEname("李四") ;
e.setSaly(900.0f) ;
e.setHiredate(new Date()) ;
e.setDept(d) ;
d.getEmps().add(e) ;
this.session.save(d);
this.session.beginTransaction().commit();
this.session.close();
}
直接就可以完成插入操作。同样,在查询的时候依然存在了延迟加载的关系。
public void find1() {
String hql = "FROM Dept d WHERE d.deptno=1";
Dept d = (Dept) this.session.createQuery(hql).uniqueResult();
System.out.println(d.getDname());
Iterator iter = d.getEmps().iterator() ;
while(iter.hasNext()){
Emp e = (Emp)iter.next() ;
System.out.println("\t |- " + e.getEname());
}
this.session.close();
}
既然存在了延迟加载,则必须在session关闭前进行加载,否则肯定会出现session已经关闭的错误。

4、总结
1、 Hibernate中推荐使用HQL的方式进行查询,通过Query接口完成
2、 Hibernate中的缓存分为一级缓存、二级缓存、查询缓存
• 一级缓存是Session级别的
• 二级缓存是SessionFactory,必须配置单独的缓存组件
• 在查询缓存中配置的话,可以减少重复查询执行SQL语句的效果
3、 容器映射技术中的Set映射是无重复的,虽然只有一个POJO类文件,但是却可以同时操作两张表,而且子表中除了关联字段之外,只能存在一个字段。
4、 Hibernate中一对多关联中,存在延迟加载,所有的延迟加载要求就默认打开。
5、作业
使用Struts + Hibernate完成地区-子地区的管理和商品类别-商品子类别管理两个程序:
• 一个地区包含多个子地区,完成之后可以再将之前的AJAX + XML程序进行修改,完成级联菜单操作。
• 一个商品类别包含多个商品子类别,完成之后使用AJAX + XML完成级联菜单。
6.1、作业一:地区-子地区
地区表字段说明:
地区表
id 地区ID(自动增长)
title 标题
子地区表字段说明:
地区子表
id 地区子表ID(自动增长)
upid 地区表id
title 子地区名称
数据库创建脚本:
USE mldnshop ;
create table area
(
id int AUTO_INCREMENT PRIMARY KEY NOT NULL,
title varchar(100) NOT NULL
) ;
CREATE TABLE areaplus (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
upid INT NOT NULL,
title varchar(100) default NULL ,
foreign key (upid) references area (id) on delete cascade
) ;
INSERT INTO area (title) VALUES
('其他'), ('北京'), ('重庆'), ('福建'), ('甘肃'), ('广东'),
('广西'), ('贵州'), ('海南'), ('河北'), ('黑龙江'), ('河南'),
('香港'), ('湖北'), ('湖南'), ('江苏'), ('江西'), ('吉林'),
('辽宁'), ('澳门'), ('内蒙古'), ('宁夏'), ('青海'), ('山东'),
('上海'), ('山西'), ('陕西'), ('四川'), ('台湾'), ('天津'),
('新疆'), ('西藏'), ('云南'), ('浙江'), ('安徽');
INSERT INTO areaplus (upid,title) VALUES
(35,'合肥'), (35,'安庆'), (35,'蚌埠'), (35,'亳州'), (35,'巢湖'), (35,'滁州'),
(35,'阜阳'), (35,'贵池'), (35,'淮北'), (35,'淮化'), (35,'淮南'), (35,'黄山'),
(35,'九华山'), (35,'六安'), (35,'马鞍山'), (35,'宿州'), (35,'铜陵'), (35,'屯溪'),
(35,'芜湖'), (35,'宣城'), (2,'北京'), (3,'重庆'), (4,'福州'), (4,'福安'),
(4,'龙岩'), (4,'南平'), (4,'宁德'), (4,'莆田'), (4,'泉州'), (4,'三明'),
(4,'邵武'), (4,'石狮'), (4,'永安'), (4,'武夷山'), (4,'厦门'), (4,'漳州'),
(5,'兰州'), (5,'白银'), (5,'定西'), (5,'敦煌'), (5,'甘南'), (5,'金昌');
INSERT INTO areaplus (upid,title) VALUES
(5,'酒泉'), (5,'临夏'), (5,'平凉'), (5,'天水'), (5,'武都'), (5,'武威'),
(5,'西峰'), (5,'张掖'), (6,'广州'), (6,'潮阳'), (6,'潮州'), (6,'澄海'),
(6,'东莞'), (6,'佛山'), (6,'河源'), (6,'惠州'), (6,'江门'), (6,'揭阳'),
(6,'开平'), (6,'茂名'), (6,'梅州'), (6,'清远'), (6,'汕头'), (6,'汕尾'),
(6,'韶关'), (6,'深圳'), (6,'顺德'), (6,'阳江'), (6,'英德'), (6,'云浮'),
(6,'增城'), (6,'湛江'), (6,'肇庆'), (6,'中山'), (6,'珠海'), (7,'南宁');
INSERT INTO areaplus (upid,title) VALUES
(7,'百色'), (7,'北海'), (7,'桂林'), (7,'防城港'), (7,'河池'), (7,'贺州'),
(7,'柳州'), (7,'钦州'), (7,'梧州'), (7,'玉林'), (8,'贵阳'), (8,'安顺'),
(8,'毕节'), (8,'都匀'), (8,'凯里'), (8,'六盘水'), (8,'铜仁'), (8,'兴义'),
(8,'玉屏'), (8,'遵义'), (9,'海口'), (9,'儋县'), (9,'陵水'), (9,'琼海'),
(9,'三亚'), (9,'五指山'), (9,'万宁'), (10,'石家庄'), (10,'保定'), (10,'北戴河'),
(10,'沧州'), (10,'承德'), (10,'丰润'), (10,'邯郸'), (10,'衡水'), (10,'廊坊');
INSERT INTO areaplus (upid,title) VALUES
(10,'南戴河'), (10,'秦皇岛'), (10,'唐山'), (10,'新城'), (10,'邢台'), (10,'张家口'),
(11,'哈尔滨'), (11,'北安'), (11,'大庆'), (11,'大兴安岭'), (11,'鹤岗'), (11,'黑河'),
(11,'佳木斯'), (11,'鸡西'), (11,'牡丹江'), (11,'齐齐哈尔'), (11,'七台河'), (11,'双鸭山'),
(11,'绥化'), (11,'伊春'), (12,'郑州'), (12,'安阳'), (12,'鹤壁'), (12,'潢川'),
(12,'焦作'), (12,'济源'), (12,'开封'), (12,'漯河'), (12,'洛阳'), (12,'南阳'), (12,'平顶山'),
(12,'濮阳'), (12,'三门峡'), (12,'商丘'), (12,'新乡');
INSERT INTO areaplus (upid,title) VALUES
(12,'信阳'), (12,'许昌'), (12,'周口'), (12,'驻马店'), (13,'香港'), (13,'九龙'),
(13,'新界'), (14,'武汉'), (14,'恩施'), (14,'鄂州'), (14,'黄冈'), (14,'黄石'),
(14,'荆门'), (14,'荆州'), (14,'潜江'), (14,'十堰'), (14,'随州'), (14,'武穴'), (14,'仙桃'),
(14,'咸宁'), (14,'襄阳'), (14,'襄樊'), (14,'孝感'), (14,'宜昌'), (15,'长沙'), (15,'常德'),
(15,'郴州'), (15,'衡阳'), (15,'怀化'), (15,'吉首'), (15,'娄底'), (15,'邵阳'), (15,'湘潭'),
(15,'益阳'), (15,'岳阳'), (15,'永州');
INSERT INTO areaplus (upid,title) VALUES
(15,'张家界'), (15,'株洲'), (16,'南京'), (16,'常熟'), (16,'常州'), (16,'海门'),
(16,'淮安'), (16,'江都'), (16,'江阴'), (16,'昆山'), (16,'连云港'), (16,'南通'),
(16,'启东'), (16,'沭阳'), (16,'宿迁'), (16,'苏州'), (16,'太仓'), (16,'泰州'),
(16,'同里'), (16,'无锡'), (16,'徐州'), (16,'盐城'), (16,'扬州'), (16,'宜兴'),
(16,'仪征'), (16,'张家港'), (16,'镇江'), (16,'周庄'), (17,'南昌'), (17,'抚州'),
(17,'赣州'), (17,'吉安'), (17,'景德镇'), (17,'井冈山'), (17,'九江'), (17,'庐山');
INSERT INTO areaplus (upid,title) VALUES
(17,'萍乡'), (17,'上饶'), (17,'新余'), (17,'宜春'), (17,'鹰潭'), (18,'长春'),
(18,'白城'), (18,'白山'), (18,'珲春'), (18,'辽源'), (18,'梅河'), (18,'吉林'),
(18,'四平'), (18,'松原'), (18,'通化'), (18,'延吉'), (19,'沈阳'), (19,'鞍山'),
(19,'本溪'), (19,'朝阳'), (19,'大连'), (19,'丹东'), (19,'抚顺'), (19,'阜新'),
(19,'葫芦岛'), (19,'锦州'), (19,'辽阳'), (19,'盘锦'), (19,'铁岭'), (19,'营口'),
(20,'澳门'), (21,'呼和浩特'), (21,'阿拉善盟'), (21,'包头'), (21,'赤峰'), (21,'东胜');
INSERT INTO areaplus (upid,title) VALUES
(21,'海拉尔'), (21,'集宁'), (21,'临河'), (21,'通辽'), (21,'乌海'), (21,'乌兰浩特'),
(21,'锡林浩特'), (22,'银川'), (22,'固原'), (22,'石嘴山'), (22,'吴忠'), (23,'西宁'),
(23,'德令哈'), (23,'格尔木'), (23,'共和'), (23,'海东'), (23,'海晏'), (23,'玛沁'),
(23,'同仁'), (23,'玉树'), (24,'济南'), (24,'滨州'), (24,'兖州'), (24,'德州'),
(24,'东营'), (24,'菏泽'), (24,'济宁'), (24,'莱芜'), (24,'聊城'), (24,'临沂'),
(24,'蓬莱'), (24,'青岛'), (24,'曲阜'), (24,'日照'), (24,'泰安');
INSERT INTO areaplus (upid,title) VALUES
(24,'潍坊'), (24,'威海'), (24,'烟台'), (24,'枣庄'), (24,'淄博'), (25,'上海'),
(25,'崇明'), (25,'朱家角'), (26,'太原'), (26,'长治'), (26,'大同'), (26,'候马'),
(26,'晋城'), (26,'离石'), (26,'临汾'), (26,'宁武'), (26,'朔州'), (26,'忻州'),
(26,'阳泉'), (26,'榆次'), (26,'运城'), (27,'西安'), (27,'安康'), (27,'宝鸡'),
(27,'汉中'), (27,'渭南'), (27,'商州'), (27,'绥德'), (27,'铜川'), (27,'咸阳'),
(27,'延安'), (27,'榆林'), (28,'成都'), (28,'巴中'), (28,'达州'), (28,'德阳');
INSERT INTO areaplus (upid,title) VALUES
(28,'都江堰'), (28,'峨眉山'), (28,'涪陵'), (28,'广安'), (28,'广元'), (28,'九寨沟'),
(28,'康定'), (28,'乐山'), (28,'泸州'), (28,'马尔康'), (28,'绵阳'), (28,'眉山'),
(28,'南充'), (28,'内江'), (28,'攀枝花'), (28,'遂宁'), (28,'汶川'), (28,'西昌'),
(28,'雅安'), (28,'宜宾'), (28,'自贡'), (28,'资阳'), (29,'台北'), (29,'基隆'),
(29,'台南'), (29,'台中'), (30,'天津'), (31,'乌鲁木齐'), (31,'阿克苏'), (31,'阿勒泰'),
(31,'阿图什'), (31,'博乐'), (31,'昌吉'), (31,'东山'), (31,'哈密');
INSERT INTO areaplus (upid,title) VALUES
(31,'和田'), (31,'喀什'), (31,'克拉玛依'), (31,'库车'), (31,'库尔勒'), (31,'奎屯'),
(31,'石河子'), (31,'塔城'), (31,'吐鲁番'), (31,'伊宁'), (32,'拉萨'), (32,'阿里'),
(32,'昌都'), (32,'林芝'), (32,'那曲'), (32,'日喀则'), (32,'山南'), (33,'昆明'),
(33,'大理'), (33,'保山'), (33,'楚雄'), (33,'东川'), (33,'个旧'),
(33,'景洪'), (33,'开远'), (33,'临沧'), (33,'丽江'), (33,'六库'), (33,'潞西'),
(33,'曲靖'), (33,'思茅'), (33,'文山'), (33,'西双版纳'), (33,'玉溪');
INSERT INTO areaplus (upid,title) VALUES
(33,'中甸'), (33,'昭通'), (34,'杭州'), (34,'安吉'), (34,'慈溪'), (34,'定海'),
(34,'奉化'), (34,'海盐'), (34,'黄岩'), (34,'湖州'), (34,'嘉兴'), (34,'金华'),
(34,'临安'), (34,'临海'), (34,'丽水'), (34,'宁波'), (34,'瓯海'), (34,'平湖'),
(34,'千岛湖'), (34,'衢州'), (34,'江山'), (34,'瑞安'), (34,'绍兴'), (34,'嵊州'),
(34,'台州'), (34,'温岭'), (34,'温州'), (34,'舟山'), (1,'其他');
6.2、作业二:商品类别-商品类别子
商品类别表:
商品类别表
id 类别编号(自动增长)
title 类别名称
img 类别图片
description 类别描述
商品子类别表:
商品类别子表
id 子类别编号
upid 父类别id编号
title 子类别名称
数据库创建脚本:
use mshop ;
DROP TABLE IF EXISTS catalogplus;
DROP TABLE IF EXISTS catalog;
CREATE TABLE catalog (
id int AUTO_INCREMENT PRIMARY KEY NOT NULL ,
title varchar(100) default NULL,
img varchar(100) default NULL,
description varchar(255) default NULL
) ;
CREATE TABLE catalogplus (
id int AUTO_INCREMENT PRIMARY KEY NOT NULL,
upid int NOT NULL ,
title varchar(100) default NULL,
foreign key (upid) references catalog (id) on delete cascade
) ;
INSERT INTO catalog (title,img,description) VALUES
('电脑、软件、网络','11540709315040.jpg','杂志 小说 瑞丽 外语 考研 求职'),
('MP3、MP4、音响','11540722111920.gif','手机 CDMA 智能 充值 配件 小灵通 蓝牙 诺基亚 三星 索爱 MOTO 拍卖'),
('手机、通讯设备、卡','11540721784890.gif','ZIPPO 打火机 瑞士军刀 刀具 男包 饰品 烟具 烟斗 酒具 配件 剃须刀'),
('数码相机、摄影摄像','11540708454570.gif','走过路过千万别错过,各种品牌液精大优惠'),
('珠宝首饰、手表、眼镜','11540708241600.jpg','HIFI音响 纽曼 CD MD 一元 99元 199元 森海塞尔'),
('彩妆、香水、护肤','11540708010040.gif','佳能 索尼 尼康 三星 配件 闪存卡 数码相机 数码单反 DV 镜头 读卡器'),
('女装、女士精品','11540707778790.gif','银饰 韩国 水晶 外贸原单 Swatch 施华洛世奇 名表 发夹 项链 钻石'),
('男装、服饰配件','11540707582540.gif','各种品牌笔记本电脑全线大优惠'),
('网络游戏虚拟商品','11540707403320.gif','各种时尚、高档MP3、MP3'),
('音乐、影视、明星、娱乐','11540707172390.gif','这是一个美得上帝也要叹息的地方!它被浓阴华盖遮蔽,恬静、怡然,没有一丝尘世的喧嚣');
INSERT INTO catalogplus (upid,title) VALUES
(1,'硬件'), (1,'全新笔记本'), (1,'二手笔记本'), (1,'PDA'), (1,'笔记本配件'),
(1,'电脑周边'), (1,'网络服务'), (3,'手机'), (3,'CDMA'), (3,'配件'),
(3,'小灵通'), (2,'便携视听'), (2,'HIFI音响'), (2,'电脑音箱'), (4,'数码相机'),
(4,'数码单反'), (4,'专业相机'), (4,'DV'), (5,'银饰'), (5,'韩国'), (5,'水晶'),
(5,'外贸'), (6,'丰胸'), (6,'Swarovski'), (6,'减肥'), (6,'护肤'), (6,'香水'),
(6,'面膜'), (6,'雅芳'), (7,'吊带衫'), (7,'背心'), (7,'针织衫'), (7,'毛衣'),
(7,'衬衫'), (7,'T恤'), (8,'毛衣'), (8,'线衫'), (8,'外套'), (8,'帽衫'),
(8,'西装'), (8,'风衣'), (9,'梦幻/大话'), (9,'魔兽'), (9,'QQ 点卡'), (9,'装备'),
(9,'帐号'), (10,'韩剧'), (10,'明星'), (10,'演唱会'), (10,'音乐CD'), (10,'电影DVD');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值