hibernate笔记
标示符属性生成策略:
1、 increment:获取最大的值,加一做为当前的属性的值,什么数据库中都可以使用。
<id name="id" type="javalang.Integer" column = "ID">
<grenrator class = "increment"> </grenrator>
</id>
2、identity:MS SQL Server、MySql和DB2中,有一个自动增长的字段。
Oracle数据库就不支持,一位Oracle数据库不支持这个
3、sequence:
4、hilo:高低位生成策略。
<id name="id" type="javalang.Integer" column = "ID">
<grenrator class = "hilo">
<param name = table >hibernate_key</param>
<param name=column>next_hivalue</param>
</grenrator>
</id>
创建一个表名字叫做hibernate_key 其中一个字段叫做next_hivalue,整形数据
5、uuid,如何数据中都可以使用,生成一串字符串,不重复的,产生的不是全数字,数度很快,它不用任何参数。
<id name=id type=java.lang.String column=ID>
<generator class=uid></generator>
</id>
6、guid:只有在ms sql和mysql中应用。
<id name=id type=java.lang.String column=ID>
<generator class=guid></generator>
</id>
7、native:根据使用的数据库的支持功能自动选择,从identity、sequence、hilo生成策略中选择一个。
8、assigned:客户包办,由客户指定
hibernate对象的生命周期:
Persistent:持久态
session.save(gb)
Transient:顺管
GuestBook g = new()
g.set(....)
....
没有调用save的()的时候
调用svae()后就变了persistent态了
detached:脱管态
session.close()
remove:删除态
session.geginTransacation().commit()
=============================================
session 脏数据的检查
GuestBook book = session.get(GuestBook.class, Integer(1));
book.set(....)
没掉用save方法,调用了set数据变脏了
Transaction tran = session.begsinStra.....
tran.commit()
调用了commit,hibernate会自动更新数据库,因为现在现在的对象处于了持久态
========session.saveOrUpdate(gb):
会自动判断,判断id是否已经存在数据库中了,自动添加或者修改。
========session.flash(),他已经跟close方法绑定了在一起了。
========session.close(),当sessin对象跟实物绑定在一起,则调用commit会自动调用了
只要是session.getCurrentSession().跟当前实物绑定session对象。
=========================================================================
不可更改的持久化对象。只读对象
<class name= table= mutiable="false">
</class>
Open Session In View模式:
比如:上面说的用getCurrentSession()的形式get到session的时候
Transaction.commit(gb)后我们又调用gb.getTitle()
则可能会抛出异常了。
Configuration config = new Configuration().configure();
SessionFactory sfac = config.buildSessionFactory();
this.session = sfac.getCurrentSession();
。。。。。。。。。。。。。
Transaction.commit()
。。。。。。
System.println(gb.getTitle())
泛型DAO的设计模式与实现:
比如与底层的数据操作,我可以用JDBC实现也可以用hibernate实现,那么这个时候我们就Kyocera用dao模型来实现,方便我们切换。
定义个泛型接口:
Public interface GenericDao<T, PK extends Serializable> {
Public T findById(PK id);
Public List<T> findAll();
…………………………
}
顶一个累实现上面的接口:
Public class GreneriacDaohibernate< T, PK extends Serializable > implements GenericDao<T, PK> {
Private Class<T> clazz;
}
集合映射:
Set:不能重复,不记录对象加入的先后顺序
sprivate Set<String> emails = new HashSet<String>();
<class name="" table="" schema="">
<id name="" type="">
<column name="" precision="" scale=""></column>
<generator class="increment"></generator>
</id>
<property name="" type="">
<column name="" not-null="" .....></column>
</property>
............
<set name="emails(对象的属性名字)" table="email">
<key column="userID" foreign="id"(对应主表对象的主键属性名) ></key>
<element type="" column="email(表的字段名字)"
</set>
</class>
List:可以重复,记录对象的加入先后顺序
private List<String> emails = new ArrayList();
<list name="" table="">
<key column="" foreign-key=""></key>
<index column="idx" type=""></index>
<element type="" column=></element>
</list>
Bag:允许重复,不记录对象的加入先后顺序
private Collection<String> emails = new ArrayList();
<bag name="" table="">
<key column="" foreign-key=""/>
<element type="" column=""/>
</bag>
IdBag: 是Bag的扩展,可以指定id值,跟List相识
---------------------------------------------------
Map映射:保存key及对应的value的,key不可以重复
Map:
eg:phonse("office", "110") phones("hone","113") phones("mobile", "333")
排序:sort是以key排序,用set或者map的sort排序,是在内存中排序再输出的。数据量大的时候不推荐用此方法排序
order by排序,按字段排序,order-by=userID desc
<map name="phones" table="userPhone" sort="natural" [order-by="phoneNumber"]>
<key column="userID" foreign-key="id"></key>
<map-key type="java.lang.String" column="usage"></map-key>
<element type="java.lang.String" column="phoneNumber"></element>
</map>
HashMap:不记录加入的加入的先后循序。
LinkedHashMap:记录加入的先后顺序。
TreeMap:支持排序
组建映射:
组建映射的单向关联、组建映射的双向关联:
<!-- 组建(component)映射,双向关联 -->
<component name="Profile" class="com.hibernate.test.study.study7.Profile">
<!-- name是 profile对象的 关联属性名字 (指定双向关联)-->
<parent name="user"/>
<property name="sex" type="java.lang.String">
<column name="sex" length="16" not-null="true" />
</property>
<property name="tel" type="java.lang.String">
<column name="tel" length="20" not-null="true" />
</property>
<property name="email" type="java.lang.String">
<column name="email" length="30" not-null="true" />
</property>
<property name="address" type="java.lang.String">
<column name="address" length="100" />
</property>
<property name="postCode" type="java.lang.String">
<column name="postCode" length="6" />
</property>
</component>
组建集合映射:
<!-- 组建集合映射 双向关联 -->
<!-- name = Product类的属性名字 table = 表的名字 -->
<set name="productImages" table="productImages">
<!-- 指定外键 -->
<key column="productID" foreign-key="id" not-null="true"></key>
<composite-element class="com.hibernate.test.study.study7.Image">
<!-- 指定Image中双向关联的属性名字 -->
<parent name="product"/>
<property name="fileName" column="fileName"></property>
<property name="filePath" column="filePath"></property>
<property name="fileSize" column="fileSize"></property>
</composite-element>
</set>
映射多对一,一对多关系 单向、双向:
一对多映射关系: 当products中有该category的一个分类的时候,即有该分类的产品存在products表的时候,mysql不允许删除该分类,Oracle好像是允许删除,然后置该产品的外键为空。
<hibernate-mapping>
<class name="com.hibernate.test.study.study8.Category" table="category" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="30" not-null="true" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" />
</property>
<!-- 映射一对多关系 name=类的关联属性名字 cascade级联-->
<set name="productses" inverse="true" [cascade="savesave-update"] >
<key>
<column name="categoryID" />
</key>
<one-to-many class="com.hibernate.test.study.study8.Products" />
</set>
</class>
</hibernate-mapping>
映射多对多对一关系:
<hibernate-mapping>
<class name="com.hibernate.test.study.study8.Products" table="products" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="100" />
</property>
<property name="price" type="java.lang.Float">
<column name="price" precision="12" scale="0" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" />
</property>
<!-- 映射多对一的关系 nameo=对象关联属性名称 必须指明class outer-join="true" 表示使用关联查询,一次查询出来-->
<many-to-one name="category" class="com.hibernate.test.study.study8.Category" outer-join="true">
<column name="categoryID" />
</many-to-one>
</class>
</hibernate-mapping>
级联:主动方执行一个动作的时候,被动方(关联方)也执行相应的动作
cascade:
none:默认
save-update: 主动方调用save update saveOrUpdate的时候关联方也执行
delete:主动方执行save的时候被动执行
delete-orphan:只应用于一对多,主动方掉delete的时候,此时不被任何一个关联对象所引用被关联对象全被删除,即删除孤立项
all:
<!-- 映射一对多关系 name=类的关联属性名字,inverse="true"控制反转, cascade级联-->
<set name="productses" inverse="true" [cascade="savesave-update"] >
<key>
<column name="categoryID" />
</key>
<one-to-many class="com.hibernate.test.study.study8.Products" />
</set>
java code:
public void addproduct2() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
session.getTransaction().begin();
Category cat = new Category();
cat.setName("U盘");
cat.setDescription("各式各样的U盘");
Products pro = new Products();
pro.setName("金斯顿1gU盘");
pro.setPrice(5999.0f);
pro.setDescription("金斯顿1gU盘金斯顿1gU盘");
Products pro2 = new Products();
pro2.setName("金斯顿2gU盘");
pro2.setPrice(5999.0f);
pro2.setDescription("金斯顿2gU盘金斯顿2gU盘");
pro.setCategory(cat);
pro2.setCategory(cat);
cat.getProductses().add(pro);
cat.getProductses().add(pro2);
session.save(cat);
session.getTransaction().commit();
session.close();
}
映射 一对一关系,单向、双向,一共有两种方式:
1、共享主键关联
2、唯一外键关联
1、共享主键关联:公用一个主键,具有相同的值。
Userinfo4.hm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study9.Userinfo4" table="userinfo4" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<!-- 指定共享主键 -->
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="email" type="java.lang.String">
<column name="email" length="30" />
</property>
<property name="tel" type="java.lang.String">
<column name="tel" length="20" />
</property>
<one-to-one name="user" class="com.hibernate.test.study.study9.User4"></one-to-one>
</class>
</hibernate-mapping>
User4.hm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study9.User4" table="user4" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="userName" type="java.lang.String">
<column name="userName" length="20" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="password" length="20" not-null="true" />
</property>
<one-to-one name="userInfo" class="com.hibernate.test.study.study9.Userinfo4"></one-to-one>
</class>
</hibernate-mapping>
java code:
public void addUser() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
session.getTransaction().begin();
User4 user = new User4();
user.setUserName("zhuxiangdong");
user.setPassword("333333");
Userinfo4 userInfo = new Userinfo4();
userInfo.setEmail("[email protected]");
userInfo.setTel("8662012");
user.setUserInfo(userInfo);
userInfo.setUser(user);
session.save(user);
session.save(userInfo);
//userInfo会自动获取user的ID作为自己的ID主键
session.getTransaction().commit();
session.close();
}
User4跟Userinfo4是双向关联的:
eg:
//通过User可以找到Userinfo
public void loadUser() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
User4 user = (User4) session.load(User4.class, new Integer(4));
System.out.println(user.getId());
System.out.println(user.getUserName());
System.out.println(user.getPassword());
Userinfo4 userInfo = user.getUserInfo();
System.out.println(userInfo.getId());
System.out.println(userInfo.getEmail());
System.out.println(userInfo.getTel());
}
//通过Userinfo可以找到User
public void loadUserinfo() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
Userinfo4 userInfo = (Userinfo4) session.load(Userinfo4.class, new Integer(4));
System.out.println(userInfo.getId());
System.out.println(userInfo.getEmail());
System.out.println(userInfo.getTel());
User4 user = userInfo.getUser();
System.out.println(user.getId());
System.out.println(user.getUserName());
System.out.println(user.getPassword());
}
2、唯一外键关联:(数据库设置的是外键不可重复,约定只有一条记录与之对应,即一对一关系),配置,我们应用多对一,一对多的配置相似。靠uniqu="true"这个类控制的。
Userinfo4.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study9.Userinfo4" table="userinfo4" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<!-- 指定共享主键 -->
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="email" type="java.lang.String">
<column name="email" length="30" />
</property>
<property name="tel" type="java.lang.String">
<column name="tel" length="20" />
</property>
<!--指定唯一外键:unique=“true”-->
<many-to-one name="user" class="com.hibernate.test.study.study9.User4" uniqu="true"></many-to-one>
</class>
</hibernate-mapping>
User4.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study9.User4" table="user4" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="userName" type="java.lang.String">
<column name="userName" length="20" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="password" length="20" not-null="true" />
</property>
<one-to-one name="userInfo" class="com.hibernate.test.study.study9.Userinfo4" unique="true"></one-to-one>
</class>
</hibernate-mapping>
映射多对多关联,单向、双向:需要借用一个中间表
Orders5.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study10.Orders5" table="orders5" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="relName" type="java.lang.String">
<column name="relName" length="20" />
</property>
<property name="tel" type="java.lang.String">
<column name="tel" length="10" />
</property>
<property name="totalMoney" type="java.lang.Float">
<column name="totalMoney" precision="12" scale="0" />
</property>
<set name="products" table="orderProduct5">
<key column="orderID"></key>
<many-to-many class="com.hibernate.test.study.study10.Products5" column="productID"></many-to-many>
</set>
</class>
</hibernate-mapping>
products5.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study10.Products5" table="products5" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="60" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" />
</property>
</class>
</hibernate-mapping>
(备注:上面只做了单向关联,但是上面呢没有双向关联的必要,若要加上双向,请加上下面的配置:)
<hibernate-mapping>
<class name="com.hibernate.test.study.study10.Products5" table="products5" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="60" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="65535" />
</property>
<set name="orders" table="Orders5">
<key column="productID"></key>
<many-to-many class="com.hibernate.test.study.study10.Orders5" column="orderID"></many-to-many>
</set>
</class>
</hibernate-mapping>
多对多关联拆分为两个一对多的关联:因为上面无法记录我们购买的数量和购买的时候的价格,因为价格是波动的,不同时期价格不同的。
Orders7.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study10.Orders7" table="orders7" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="relName" type="java.lang.String">
<column name="relName" length="20" />
</property>
<property name="tel" type="java.lang.String">
<column name="tel" length="10" />
</property>
<property name="totalMoney" type="java.lang.Float">
<column name="totalMoney" precision="12" scale="0" />
</property>
<!-- 同时指定级联朝着 -->
<set name="orderProducts" cascade="save-update">
<key>
<column name="orderID"></column>
</key>
<one-to-many class="com.hibernate.test.study.study10.Orderproduct7"/>
</set>
</class>
</hibernate-mapping>
orderProduct7.hbm.xml:
<hibernate-mapping>
<class name="com.hibernate.test.study.study10.Orderproduct7" table="orderProduct7" catalog="test_mysql">
<!-- 指定复合主键 -->
<composite-id>
<key-many-to-one name="product" class="com.hibernate.test.study.study10.Products7">
<column name="productID" />
</key-many-to-one>
<key-many-to-one name="order" class="com.hibernate.test.study.study10.Orders7">
<column name="orderID" />
</key-many-to-one>
<key-property name="quantity" type="java.lang.Integer">
<column name="quantity" />
</key-property>
<key-property name="price" type="java.lang.Float">
<column name="price" precision="12" scale="0" />
</key-property>
</composite-id>
</class>
</hibernate-mapping>
主意:如果我们需要使用复合主键的时候,如果我们使用set集合的时候,因为set是不允许重复的,如果元素是一个对象的时候,java可能不知道如何去判断着两个对象是否相等,这个时候就需要我们重写
对象的equals方法,而equals方法用到hashCode方法它是一个比较技术,所以我们 也要重写hashcode方法:
eg:
public class Orders7 implements java.io.Serializable {
// Fields
private Integer id;
private String relName;
private String tel;
private Float totalMoney;
private Set orderProducts = new HashSet(0);
........
}
public class Orderproduct7 implements java.io.Serializable {
private static final long serialVersionUID = -2002077161452152357L;
// Fields
private Orders7 order;
private Products7 product;
private Integer quantity;
private float price;
.............
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((order == null) ? 0 : order.hashCode());
result = PRIME * result + Float.floatToIntBits(price);
result = PRIME * result + ((product == null) ? 0 : product.hashCode());
result = PRIME * result + ((quantity == null) ? 0 : quantity.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;
final Orderproduct7 other = (Orderproduct7) obj;
if (order == null) {
if (other.order != null)
return false;
} else if (!order.equals(other.order))
return false;
if (Float.floatToIntBits(price) != Float.floatToIntBits(other.price))
return false;
if (product == null) {
if (other.product != null)
return false;
} else if (!product.equals(other.product))
return false;
if (quantity == null) {
if (other.quantity != null)
return false;
} else if (!quantity.equals(other.quantity))
return false;
return true;
}
}
一个特殊的多对多关联:无限子类别:
java code:
// Fields
private Integer id;
private String name;
private String description;
private Integer parentId;
private Integer level;
//设置父类
private Category1 category;
//设置子类
private Set categorys = new HashSet(0);
// Constructors
public Category1 getCategory() {
return category;
}
配置:
Category.hbm.xml:
<class name="com.hibernate.test.study.study10.Category1" table="category1" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="30" not-null="true" />
</property>
<property name="description" type="java.lang.String">
<column name="description" length="200" not-null="true" />
</property>
<property name="parentId" type="java.lang.Integer">
<column name="parentID" />
</property>
<property name="level" type="java.lang.Integer">
<column name="level" />
</property>
<!-- 配置父类 -->
<many-to-one name="category" class="com.hibernate.test.study.study10.Category1" fetch="select" insert="false" update="false">
<column name="parentID"></column>
</many-to-one>
<!-- 配置子类 -->
<set name="categorys" inverse="true">
<key>
<column name="parentID"></column>
</key>
<one-to-many class="com.hibernate.test.study.study10.Category1"/>
</set>
</class>
Criteria查询
public void loadByE() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
session.getTransaction().begin();
Criteria cri = session.createCriteria(Guestbook11.class);
// Criterion criterion = Restrictions.eq("name", "朱向东");
// Criterion criterion = Restrictions.between("id", 1, 2);
// Criterion criterion = Restrictions.gt("id", 2);
// Criterion criterion1 = Restrictions.like("name", "朱%");
// Criterion criterion2 = Restrictions.between("id", 1, 2);
//Criterion orCriterion = Restrictions.or(criterion1, criterion2);
//and 复合条件
// cri.add(criterion1);
// cri.add(criterion2);
// cri.add(orCriterion);
//排序设置
cri.addOrder(Order.asc("id"));
//设置分页
// cri.setMaxResults(4); //设置返回的数据的条数
// cri.setFirstResult(0); //设置从第几条数据开始读
//设置值返回一条记录
// cri.setMaxResults(1);
// //设置返回一条记录的时候,不用去读list集合了,直接用uniqueRest()方法
// Guestbook11 tempGb = (Guestbook11) cri.uniqueResult();
// System.out.println(tempGb.getId()+ "---" + tempGb.getName());
List<Guestbook11> list = cri.list();
for (Guestbook11 item : list) {
System.out.println(item.getId()+ "---" + item.getName());
}
session.getTransaction().commit();
session.close();
}
聚集函数查询:
public void loadByE2() {
Session session = HibernateSessionFactoryUtil.sfac.openSession();
session.getTransaction().begin();
Criteria criteria = session.createCriteria(Guestbook11.class);
//聚集函数查询
// criteria.setProjection(Projections.max("id"));
// Integer maxId = (Integer) criteria.uniqueResult();
// System.out.println(maxId.intValue());
//多个聚集函数查询
// ProjectionList projectionList = Projections.projectionList();
// projectionList.add(Projections.max("id"));
// projectionList.add(Projections.rowCount());
// projectionList.add(Projections.count("id"));
// projectionList.add(Projections.min("id"));
// projectionList.add(Projections.sum("id"));
// projectionList.add(Projections.avg("id"));
// criteria.setProjection(projectionList);
// Object[] objects = (Object[]) criteria.uniqueResult();
// for(Object item : objects) {
// System.out.println(item.toString());
// }
session.getTransaction().commit();
session.close();
}
分组查询
Criteria criteria = session.createCriteria(Guestbook11.class);
criteria.setProjection(Projections.groupProperty("name"));
List<String> list = criteria.list();
for(String item : list) {
System.out.println(item);
}
分组统计查询:
Criteria criteria = session.createCriteria(Guestbook11.class);
ProjectionList prolist = Projections.projectionList();
prolist.add(Projections.groupProperty("name"));
prolist.add(Projections.rowCount());
criteria.setProjection(prolist);
List<Object[]> list = criteria.list();
for(Object[] item : list) {
for (Object item2 : item) {
System.out.print(item2);
}
System.out.println();
}
投影查询:
criteria.setProjection(Property.forName("name"));
criteria.setProjection(Property.forName("id"));
......
//根据实例查询
Guestbook11 gb = new Guestbook11();
gb.setName("朱向东");
Criteria criteria = session.createCriteria(Guestbook11.class);
criteria.add(Example.create(gb));
List<Guestbook11> list = criteria.list();
for(Guestbook11 item : list) {
System.out.println(item.getName());
}
org.hibernate.criterion.Restrictions 类的方法:
HQL与Native SQL查询
Query接口的常用方法:
list()
iterate() //1+N方式查询,会使用非常多sql语句,先把所有的id查出来放在缓存,在根据缓存中的id一个一个区查询所有记录,
setMaxResults()
setFirstResult()
uniqueRestlt()
Query query = session.createQuery("From GuestBook11");
query.setMaxResults(20);
query.setFirstResult(0);
//query.serMaxResults(1);
//Guestbook11 gb = (Guestbook11) query.uniqueResult();
List<Guestbook11> list = query.list();
//Iterate iterate = query.iterate();
-------------------------------------------------------------------------
HQL:
Query query = session.createQuery("select id, title, name form guestbook");
List<Object[]> list = query.list();
//一定要保证这种类型的构造方法存在
//Query query = session.createQuery("select new Guestbook11(id, title, name) from guestbook11");
//List<Guestbook11> list = query.list();
//Query query = session.createQuery("select new Map(id, title, name) from guestbook11");
//List<Map> list = query.list();
//for(Map m : list) {
// m.get("0"); m.get("1"); m.get("3");
//}
//使用别名 key value一一对应
//Query query = session.createQuery("select new Map(gb.id as id, gb.title as title, gb.name as name) from guestbook11 as gb");
//List<Map> list = query.list();
//for(Map m : list) {
// m.get("id"); m.get("title"); m.get("name");
//}
----------------------------------------------------------------------
"from guestbook where name like '%liu%'"
"from guestbook where name like '?liu%'"
"from guestbook where name like 'liu%'"
"from guestbook where name like '%liu'"
"from guestbook where name not like 'liu%'"
"from guestbook where id>100 order by id desc"
"from guesbook where not (id>1) order by id, price asc "
session.createQuery("from guestbook id>:myid")
query.setInteger("mydi", 12);
Query q = session.createQuery("select avb(price), count(*) from product group by category.id having price > 12.1");
hibernate与search
搜索引擎:
全文搜索引擎:Google 百度 雅虎
目录索引搜索引擎:黄页等。。。。
元搜索引擎:搜索的数据来自于多个搜索引擎数据的组合。
Lucene:java领域的全文搜索的工具包,http://lucene.apache.org
Hibernate Search:支持索引数据的自动更新,支持众多的搜索方式。。。。。。。
继承映射
方法一:把所有子类信息放到一个表中;它支持多态查询,并且多态查询的性能高,但是会导致数据库空间的浪费。
<hibernate-mapping>
<class name="com.hibernate.test.study13.car13" table="car13" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<discriminator column="carType"></discriminator>
<property name="createDate" type="java.util.Date">
<column name="createDate" length="0" not-null="true" />
</property>
<property name="color" type="java.lang.String">
<column name="color" length="10" not-null="true" />
</property>
<subclass name="com.hibernate.test.study13.minCar13" discriminator-value="minCar">
<property name="isBaoMa" type="java.lang.String">
<column name="isbaoma" length="10" not-null="false" />
</property>
</subclass>
<subclass name="com.hibernate.test.study13.bigCar13" discriminator-value="bigCar">
<property name="isDongFeng" type="java.lang.String">
<column name="isdongfeng" length="10" not-null="false" />
</property>
</subclass>
</class>
</hibernate-mapping>
javacode:
public void insertMinCar() {
minCar13 mcar = new minCar13();
mcar.setColor("blue");
mcar.setCreateDate(new Date("2/2/2010"));
mcar.setIsBaoMa("yes");
bigCar13 bcar = new bigCar13();
bcar.setColor("white");
bcar.setCreateDate(new Date("9/9/1999"));
bcar.setIsDongFeng("yes");
Session session = HibernateSessionFactoryUtil.sfac.openSession();
session.getTransaction().begin();
session.save(mcar);
session.save(bcar);
session.getTransaction().commit();
session.close();
}
方法二:父类定义为abstract,所有的子类对应一个表,并且子类的表多包涵共同的属性,两表无外键关联等;辞方式支持多态查询,多态查询的性能不理想。
<hibernate-mapping>
<class name="com.hibernate.test.study13.car13" table="car13" catalog="test_mysql" abstract=“true”>
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="createDate" type="java.util.Date">
<column name="createDate" length="0" not-null="true" />
</property>
<property name="color" type="java.lang.String">
<column name="color" length="10" not-null="true" />
</property>
<union-subclass name="com.hibernate.test.study13.minCar13" table="minCar">
<property name="isBaoMa" type="java.lang.String">
<column name="isbaoma" length="10" not-null="false" />
</property>
</union-subclass>
<union-subclass name="com.hibernate.test.study13.bigCar13" table="bigCar">
<property name="isDongFeng" type="java.lang.String">
<column name="isdongfeng" length="10" not-null="false" />
</property>
</union-subclass>
</class>
</hibernate-mapping>
方法三:每个类多用对应一个表,把公共的信息放到父类对应的表,子类对应的信息放到子类对应的表,两字表通过外键关联父类表,可以设置即是主键也是外键来实现。查询的时候会用到连接查询,多态查询的时候会连接查询。性能较高,复合关系数据库的设计(公共信息放到一个表中),缺点关联查询效率不太高,因为要操作多个表。
<hibernate-mapping>
<class name="com.hibernate.test.study13.car13" table="car13" catalog="test_mysql">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="createDate" type="java.util.Date">
<column name="createDate" length="0" not-null="true" />
</property>
<property name="color" type="java.lang.String">
<column name="color" length="10" not-null="true" />
</property>
<joined-subclass name="com.hibernate.test.study13.minCar13" table="minCar">
<key column="id" forign-key="id"></key>
<property name="isBaoMa" type="java.lang.String">
<column name="isbaoma" length="10" not-null="false" />
</property>
</joined-subclass>
<joined-subclass name="com.hibernate.test.study13.bigCar13" table="bigCar">
<key column="id" forign-key="id"></key>
<property name="isDongFeng" type="java.lang.String">
<column name="isdongfeng" length="10" not-null="false" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
Hibernate事物管理
Hibernate中的事物:hibernate中有两种事物的管理凡是,默认的是采用jdbc的方式去管理,另外可以可用JTA来管理,这种管理方式一般用于多数据库操作的情况下比较多。
<hibernate-configuration>
<session-factory>
<!--设定事物管理的工厂类-->
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</protery>
</protery>
</session-factory>
</hibernate-configuration>
一系列的数据库的操作组成一个单元,要么全部执行,要么全部取消(一荣俱荣,一损俱损)。这个单元我们可以成为一个事物
事物的特性:
原子性,一致性(数据的一致性),隔离性(一个事物没完成,避免另外一个事物的干扰),持久性(当中断了,如断电了,下一次启动的时候能自动的全部回滚。。。。)。
数据并发访问有可能引发的问题:
1、丢失更新。
2、脏读。
3、不开重复读:第一次与第一次读出来的数据不一致。
4、幻读:a事物读取了某个表的记录,发现40条记录,后来又读了一次,却发现41条记录了(b事物在期间增加了一条记录,并且提交了事物)。
事物隔离级别:
1、Read Uncommitted
2、Read Commited 某个事物仅可以读,不能修改和删除另外一个事物提交了的数据。
3、Repeatable Read 某个事物已经读取的数据,不允许其他事物写入
4、Serializable 所有的事物只能像序列化的执行,一个一个来。
org.hibernate.Transaction
Commit()
Rollback()
锁:
悲观锁:其使用具有完全的排他性,性能比较低。
方法一:
Query query = session.crateQuery("From guestbook gb")
query.setLockMode("gb", LockMode.UPGRADE);
方法二:
GuestBook gb = (GuestBook) session.get(GuestBook.class, new Integer(1));
session.lock(gb, LockMode.UPGRADE);
方法三:
GuestBook gb = (Guestbook)session.get(GuestBook.class, new Integer(1), LockMode,UPGRADE);
乐观锁:多个事物同时去更新一个数据的时候,另外一个更新动作会发生异常。
版本号方法实现:
在表中加一个version来记录版本号,这个字段让Hibernate去操作它,不是人为去操作。
public class Guestbook implements java.io.Serializable {
//用来记录版本号,不需要提供setter getter方法
private Integer version;
}
<class name="com.test.Guestbook" table="" optimistic-lock="version">
<id name="" type=""> </id>
<version name="version" column="version" access="field"></version>
</class>
access="field"表示这个字段有Hibernate去管理,不用提哦那个getter和setter方法。
时间戳实现乐观锁:表字段的类型是 TMESTAMP类型
public class Guestbook implements java.io.Serializable{
private java.sql.Timestamp updateTime;
}
<class name="" table="">
<id name="" type=""></id>
<timestamp name="updateTime" column="updateTime" access="field"></timestamp>
</class>
Hibernate过滤器
类似servlt过滤器,配置在映射文件中
错误记录:
关于hibernate从 mysql 到 mssql的 转换一直找不到错误的地方,昨天晚上发现,对于mssql下的map文件,
如
<class name="edu.lhq.pojo.Userinfo" table="userinfo" catalog="gjms">
必须再添加一个schema="dbo"的属性
因为在mssql中,表是使用gjms.dbo.userinfo来访问的,所以schema属性值可以根据在企业管理器中看到的来设置,初步判断应该是权限值,正确的语句如下:
<class name="edu.lhq.pojo.Userinfo" table="userinfo" schema="dbo" catalog="gjms">
因为在mysql中没有这一说所以在mssql中需要补上。
Hibernate 添加到数据库中乱码:
在Hibernate .cfg.xml加上 connection.characterEncoding 的配置:
<property name="connection.characterEncoding">utf-8</property>
SSH框架中调用HibernateDaoSupport.getTemplate().save(obj)后,能保存到缓存中,单没有提交到数据中:只需早Hibernate.cfg.xml中加入autocommit配置:
<property name="hibernate.connection.autocommit">true</property>