父类采用joined-subclassdlgitem元素的继承映射,子类还要映射文件吗

Hibernate&继承树&复合主键&悲乐观锁&HQL
表的继承映射:&
每棵继承树映射成一张表
1、理解如何映射
因为类继承树肯定是对应多个类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。用hibernate实现这种策略的时候,有如下步骤:
* 父类用普通的&class&标签定义
&* 在父类中定义一个discriminator,即指定这个区分的字段的名称和类型&&&&&&
&如:&discriminator column=”XXX” type=”string”/&
* 子类使用&subclass&标签定义,在定义subclass的时候,需要注意如下几点:
&* Subclass标签的name属性是子类的全路径名
* 在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来区分不同类的字段)&的值Subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在subclass标签的内部。
&class name="Animal" table="t_animal"
lazy="false" &
name="id"&
&&generator
class="native"/&
&&discriminator column="type"
type="string"/&//是HQL中的類型,可換為java.lang.String
&property name="name"/&
&property name="sex"/&
&subclass name="Pig"
discriminator-value="P"&
&&property
name="weight"/&
&&/subclass&
&&subclass
name="Bird"
discriminator-value="B"&
&&property
name="height"/&
&&/subclass&
2、理解如何存储
存储的时候hibernate会自动将鉴别字段值(property)插入到数据库中,在加载数据的时候,hibernate能根据这个鉴别值正确的加载对象。
多态查询:在hibernate加载数据的时候能鉴别出正真的类型(instanceOf)
&& get支持多态查询
&& load只有在lazy=false,才支持多态查询
&& hql支持多态查询&&
&每个子类映射成一张表
1、理解如何映射
这种策略是使用joined-subclass标签来定义子类的。父类、子类,每个类都对应一张数据库表。
在父类对应的数据库表中,实际上会存储所有的记录,包括父类和子类的记录;在子类对应的数据库表中,&这个表只定义了子类中所特有的属性映射的字段。子类与父类,通过相同的主键值来关联。实现这种策略的时候,有如下步骤:
父类用普通的&class&标签定义即可
父类不再需要定义discriminator字段
子类用&joined-subclass&标签定义,在定义joined-subclass的时候,需要注意如下几点:
&* Joined-subclass标签的name属性是子类的全路径名
* Joined-subclass标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来关联的。&如:&key
column=”PARENT_KEY_ID”/&,这里的column,实际上就是父类的主键对应的映射字段名称。
* Joined-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。 当Joined-subclass标签的定义与class标签平行的时候,需要在Joined-subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在joined-subclass标签的内部。
&&class name="Animal"
table="t_animal"&
&id name="id"&
&&generator
class="native"/&
&property name="name"/&
&&property
name="sex"/&
&joined-subclass
name="Pig" table="t_pig"&
column="pid"/&
&&property
name="weight"/&
&&&&&&/joined-subclass&
&joined-subclass name="Bird"
table="t_bird"&
column="bid"/&
&property name="height"/&
&&/joined-subclass&
&每个具体类映射成一张表
1、理解如何映射
&这种策略是使用union-subclass标签来定义子类的。每个子类对应一张表,而且这个表的信息是完备的,
&即包含了所有从父类继承下来的属性映射的字段(这就是它跟joined-subclass的不同之处,joined-subclass定义的子类的表,只包含子类特有属性映射的字段)。
实现这种策略的时候,有如下步骤:
&* 父类用普通&class&标签定义即可
* 子类用&union-subclass&标签定义,在定义union-subclass的时候,需要注意如下几点:
* Union-subclass标签不再需要包含key标签(与joined-subclass不同)
&* Union-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。 当Union-subclass标签的定义与class标签平行的时候,需要在Union-subclass标签中,添加extends属性,里面的值是父类的全路径名称。
* 子类的其它属性,像普通类一样,定义在Union-subclass标签的内部。这个时候,虽然在union-subclass里面定义的只有子类的属性,&但是因为它继承了父类,所以,不需要定义其它的属性,在映射到数据库表的时候,依然包含了父类的所有属性的映射字段。
&&class name="Animal"
abstract="true"&&&&
//abstract表明animal表是抽象的,空的,不會生成實體表&&&&
&id name="id"&
&generator class="assigned"/&&&
注意:在保存对象的时候id是不能重复的(不能使用自增生成主键)&
&&&&&&/id&
&&property
name="name"/&
&property name="sex"/&
&union-subclass name="Pig"
table="t_pig"&
&&property
name="weight"/&
&&&&&&/union-subclass&
&&union-subclass name="Bird"
table="t_bird"&
&&property
name="height"/&
&&/union-subclass&
&&/class&&
hibernate,componentoidcomponentDDD
name="com.bjsxt.hibernate.User"
table="t_user"&
name="id"&
&&&&&&&&&&generator
class="native"/&
&&&&&&&/id&
&&&&&&&property
name="name"/&
&&&&&&&component
name="contact"&
&&&&&&&&&&&&property
name="email"/&
&&&&&&&&&&&&property
name="address"/&
&&&&&&&&&&&&property
name="zipCode"/&
&&&&&&&&&&&&property
name="contactTel"/&
&&&&&&&/component&
&&&&/class&
User user = new User();
&&&&user.setName("");&&&&&&&&&&&&&&&&
&&&&Contact
contact = new
Contact();
&&&&contact.setAddress("xxxxx");
&&&&contact.setEmail("");
&&&&contact.setZipCode("1111111");
&&&&contact.setContactTel("");
&&&&user.setContact(contact);
&&&&session.save(user);
中,在实体中只需要持有主键类的一个引用就可以了。
* hashcodeequals
name="com.bjsxt.hibernate.FiscalYearPeriod"
table="t_fiscal_year_period"&
&composite-id
name="fiscalYearPeriodPK"&
&&&&&&&&&&&&key-property
name="fiscalYear"/&
&&&&&&&&&&&&key-property
name="fiscalPeriod"/&&
&&&&&&/composite-id&
&&&&&&property
name="beginDate"/&
&&&&&&property
name="endDate"/&
&&&&&&property
name="periodSts"/&
&&&/class&
&&&&&&FiscalYearPeriod
fiscalYearPeriod = new FiscalYearPeriod();&
&&&FiscalYearPeriodPK
pk = new FiscalYearPeriodPK();
&&&pk.setFiscalYear(2008);
&&&pk.setFiscalPeriod(8);
fiscalYearPeriod.setFiscalYearPeriodPK(pk);
&&&fiscalYearPeriod.setBeginDate(new
&&&fiscalYearPeriod.setEndDate(new
&&&fiscalYearPeriod.setPeriodSts("Y");
&&&session.save(fiscalYearPeriod);
FiscalYearPeriodPK pk = new FiscalYearPeriodPK();
&&&&pk.setFiscalYear(2008);
&&&&pk.setFiscalPeriod(8);
&&&&FiscalYearPeriod
fiscalYearPeriod =
(FiscalYearPeriod)session.load(FiscalYearPeriod.class,
&&&&System.out.println(fiscalYearPeriod.getPeriodSts());
ListSetMap
name="com.bjsxt.hibernate.CollectionMapping"
table="t_CollectionMapping"&
&&&&&&&&&&
&id name="id"&
&&&&&&&&&&&&&&&&
&generator
class="native"/&
&&&&&&&&&&
&&&&&&&&&&
name="name"/&
&&&&&&&&&&
&set name="setValue"
table="t_set_value"&
&&&&&&&&&&&&&&&&
column="set_id"/&
&&&&&&&&&&&&&&&&
&element type="string"
column="set_value"/&
&&&&&&&&&&
&&&&&&&&&&
name="listValue"
table="t_list_value"&
&&&&&&&&&&&&&&&&
column="list_id"/&
&&&&&&&&&&&&&&&&
&list-index
column="list_index"/&&
&&&&&&&&&&&&&&&&
&element type="string"
column="list_value"/&
&&&&&&&&&&
&&&&&&&&&&
name="arrayValue"
table="t_array_value"&
&&&&&&&&&&&&&&&&
column="array_id"/&
&&&&&&&&&&&&&&&&
&list-index
column="array_index"/&&&
&&&&&&&&&&&&&&&&
&element type="string"
column="array_value"/&
&&&&&&&&&&
&&&&&&&&&&
&map name="mapValue"
table="t_map_value"&
&&&&&&&&&&&&&&&&
column="map_id"/&
&&&&&&&&&&&&&&&&
&map-key type="string"
column="map_key"/&
&&&&&&&&&&&&&&&&
&element type="string"
column="map_value"/&
&&&&&&&&&&
CollectionMapping c = new CollectionMapping();
&&&&c.setName("xxx");
&&&&Set setValue = new
HashSet();
&&&&setValue.add("a");
&&&&setValue.add("b");
&&&&c.setSetValue(setValue);
&&&&List listValue = new
ArrayList();
&&&&listValue.add("c");
listValue.add("d");
&&&&c.setListValue(listValue);
&&&&String[] arrayValue = new
String[]{"e", "f"};
&&&&c.setArrayValue(arrayValue);
&&&&Map mapValue = new
HashMap();
&&&&mapValue.put("k1",
&&&&mapValue.put("k2",
&&&&c.setMapValue(mapValue);&&&&&&&
CollectionMapping c =
(CollectionMapping)session.load(CollectionMapping.class,
System.out.println("name=" + c.getName());
System.out.println("setvalue=" +
c.getSetValue());
System.out.println("mapvalue=" +
c.getMapValue());
System.out.println("listvalue=" +
c.getListValue());
&class name="com.bjsxt.hibernate.Inventory"
table="t_inventory"&
&&&&&&&&&&
&id name="itemNo"&
&&&&&&&&&&&&&&&&
&generator
class="native"/&
&&&&&&&&&&
&&&&&&&&&&
name="itemName"/&
&&&&&&&&&&
name="quantity"/&
Inventory inv = (Inventory)session.load(Inventory.class, 1,
LockMode.UPGRADE);
System.out.println("itemName=" +
inv.getItemName());
&&&System.out.println("quantity="
+ inv.getQuantity());
&&&inv.setQuantity(inv.getQuantity()
&&&session.update(inv);
versionversion,如果提交数据时版本号小于或等于数据表中的版本号,则认为数据是过期的,否则给予更新。
&class name="com.bjsxt.hibernate.Inventory"
table="t_inventory" optimistic-lock="version"&
&&&&&&&&&&
&id name="itemNo"&
&&&&&&&&&&&&&&&&
&generator
class="native"/&
&&&&&&&&&&
&&&&&&&&&&
name="version"/&
&&&&&&&&&&
name="itemName"/&
&&&&&&&&&&
name="quantity"/&
public class Inventory
private int itemNo;&&&&&
private String itemN&&&&
private int version;
Inventory inv = (Inventory)session.load(Inventory.class,
System.out.println("itemName=" +
inv.getItemName());
&System.out.println("version=" +
inv.getVersion());
System.out.println("quantity=" +
inv.getQuantity());
inv.setQuantity(inv.getQuantity() - 200);
&&&&session.update(inv);
不用手动去修改version,系统自动会修改.
hibernate查询语言hql
在hql中关键字不区分大小写,但是属性和类名区分大小写
1、简单属性查询【重要】
* 单一属性查询,返回结果集属性列表,元素类型和实体类中相应的属性类型一致
&* 多个属性查询,返回的集合元素是对象数组,数组元素的类型和对应的属性在实体类中的类型一致,数组的长度取决与select中属性的个数
//查询多个属性,其集合元素是对象数组&&&&&
&&//数组元素的类型和对应的属性在实体类中的类型一致
//数组的长度取决与select中属性的个数
&&&List students
= session.createQuery("select id, name from Student").list();
&&&for (Iterator
iter=students.iterator(); iter.hasNext();) {
&&&&Object[]
obj = (Object[])iter.next();
&&&&System.out.println(obj[0]
+ "," + obj[1]);
如果认为返回数组不够对象化,可以采用hql动态实例化Student对象,需要在实体类中提供相应的构造方法。&&&&&&&&&
//如果认为返回数组不够对象化,可以采用hql动态实例化Student对象
&&&//此时list中为Student对象集合
&&&List students
= session.createQuery("select new Student(id, name) from
Student").list();
&&&for (Iterator
iter=students.iterator(); iter.hasNext();) {
&&&&Student
student = (Student)iter.next();
&&&&System.out.println(student.getId()
+ "," + student.getName());
2、实体对象查询【重要】
1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题,所谓的N+1是在查询的时候发出了N+1条sql语句
& 1: 首先发出一条查询对象id列表的sql
根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句
&* list和iterate的区别?
&* list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题
3、条件查询【重要】&
&* 可以采用拼字符串的方式传递参数
&* 可以采用?来传递参数(索引从0开始)
&&&&&&&&&&&&
//可以使用?方式传递参数
&&&&&&&&&&
&&//参数的索引从0开始
&&&&&&&&&&
&&//传递的参数值,不用单引号引起来
&&&&&&&&&&
&&//注意方法链编程
&&&&&&&&&&&
List students = session.createQuery("select s.id, s.name from
Student s where s.name like ?")&.setParameter(0,
"%1%").list();
可以采用 :参数名 来传递参数
&&&&&&&&&&&
//使用 :参数名称 的方式传递参数值
students = session.createQuery("select s.id, s.name from Student s
where s.name like :myname").setParameter("myname",
"%1%").list();&&&
如果传递多个参数,可以采用setParamterList方法
&&&&&&&&&&&
//支持in,需要使用setParameterList进行参数传递
&&&&&&&&&&&
List students = session.createQuery("select s.id, s.name from
Student s where s.id
in(:myids)")&.setParameterList("myids", new
Object[]{1, 2, 3, 4,
5})&.list();
* 在hql中可以使用数据库的函数,如:date_format
&&&//查询2008年2月创建的学生
&&&&&&&&&&
&List students = session.createQuery("select s.id,
s.name from Student s where date_format(s.createTime,
'%Y-%m')=?").setParameter(0, "2008-02").list();
//查询到创建的学生
&&List students =
session.createQuery("select s.id, s.name from Student s where
s.createTime between ? and ?").setParameter(0,
sdf.parse(" 00:00:00"))
&&&&&&&&&.setParameter(1,
sdf.parse(" 23:59:59"))&.list();
4、hibernate也支持直接使用sql进行查询
5、外置命名查询
在映射文件中采用&query&标签来定义hql
&* 在程序中采用session.getNamedQuery()方法得到hql查询串
6、查询过滤器&
&* 在映射文件中定义过滤器参数
&* 在类的映射中使用这些参数
* 在程序中启用过滤器
7、分页查询【重要】&
&* setFirstResult(),从0开始
* setMaxResults,每页显示多少条数据
8、对象导航查询,在hql中采用 . 进行导航【重要】
&List students = session.createQuery("select
s.name from Student s where s.classes.name like '%1%'").list();
9、连接查询【重要】
List students = session.createQuery("select c.name, s.name from
Student s inner join s.classes c").list();
外连接(左连接/右连接)&
List students = session.createQuery("select c.name, s.name from
Classes c left join c.students s").list();
&&&&&&&&&&&
List students = session.createQuery("select c.name, s.name from
Classes c right join c.students s").list();
10、统计查询【重要】
&List students =session.createQuery("select
c.name, count(s) from Student s join s.classes c " +"group by
c.name order by c.name").list();
11、DML风格的操作(尽量少用,因为和缓存不同步)
session.createQuery("update Student s set s.name=? where s.id
&&&&&&&&&&&&&
&.setParameter(0, "李四")
&&&&&&&&&&
&&&.setParameter(1,
&&&&&&&&&&
&&&.executeUpdate();
hibernate一级缓存&
&&&&一级缓存很短和session的生命周期一致,一级缓存也叫session级的缓存或事务级缓存
那些方法支持一级缓存:
* iterate(查询实体对象)&
如何管理一级缓存:
session.clear(),session.evict()&
如何避免一次性大量的实体数据入库导致内存溢出
&* 先flush,再clear&
&&&&如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具
hibernate二级缓存
二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
二级缓存的配置和使用:
&* 将echcache.xml文件拷贝到src下
&* 开启二级缓存,修改hibernate.cfg.xml文件
&&&property
name="hibernate.cache.use_second_level_cache"&true&/property&
&* 指定缓存产品提供商,修改hibernate.cfg.xml文件
& &&property
name="hibernate.cache.provider_class"&org.hibernate.cache.EhCacheProvider&/property&
&* 指定那些实体类使用二级缓存(两种方法)
在映射文件中采用&cache&标签
在hibernate.cfg.xml文件中,采用&class-cache&标签&&
二级缓存是缓存实体对象的
&了解一级缓存和二级缓存的交互
hibernate查询缓存
查询缓存是针对普通属性结果集的缓存,对实体对象的结果集只缓存id。
&查询缓存的生命周期,当前关联的表发生修改,那么查询缓存生命周期结束
查询缓存的配置和使用:
* 在hibernate.cfg.xml文件中启用查询缓存,如:
&&&&&&&&&&&
name="hibernate.cache.use_query_cache"&true&/property&
在程序中必须手动启用查询缓存,如:
&&&&&&&&&&
&query.setCacheable(true);&&&
hibernate抓取策略(单端代理的批量抓取)
保持默认,同fetch="select",如:
&many-to-one name="classes" column="classesid"
fetch="select"/&
fetch="select",另外发送一条select语句抓取当前对象关联实体或集合&
设置fetch="join",如:
&many-to-one name="classes" column="classesid"
fetch="join"/&
fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合
&& 此时lazy会失效
hibernate抓取策略(集合代理的批量抓取)
保持默认,同fetch="select",如:
&set name="students" inverse="true" cascade="all"
fetch="select"&
fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
设置fetch="join",如:
&set name="students" inverse="true" cascade="all"
fetch="join"&
fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合
& &此时lazy会失效
设置fetch="subselect",如:
&set name="students" inverse="true" cascade="all"
fetch="subselect"&
fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合
hibernate抓取策略,,batch-szie在&class&上的应用
batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml
&class name="Classes" table="t_classes"
batch-size="3"&
hibernate抓取策略,batch-szie在集合上的应用&&&
batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml
&set name="students" inverse="true" cascade="all"
batch-size="5"&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 subclass 的文章

 

随机推荐