hibernate 简介:
hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库。
hibernate核心接口
session:负责被持久化对象CRUD操作
sessionFactory:负责初始化hibernate,创建session对象
configuration:负责配置并启动hibernate,创建SessionFactory
Transaction:负责事物相关的操作
Query和Criteria接口:负责执行各种数据库查询
hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory
hibernate对象的三种状态:
1,Transient 瞬时 :对象刚new出来,还没设id,设了其他值。内存中临时存在,数据库没有对应记录,瞬时状态的对象允许直接使用
2,Persistent 持久:调用了save()、saveOrUpdate(),就变成Persistent,有id。数据库中有对应记录,并且处于session缓存区中
3,Detached 脱管 : 当session close()完之后,变成Detached。数据库有对应的记录,脱离session缓存区中
hibernate-取消关联外键引用数据丢失抛异常的设置@NotFound
@Cascade(CascadeType.ALL)级联,可以通过注解添加也可以通过属性添加在如@onetomeny
@OnetoMany(mappedBy = "comment")
默认情况下,双方都负责关联关的维护。
但是如果让一方负责关联关系的维护,多了一条update语句(也就是级联会访问另一张表)
一般情况下,一方不负责关联关系的维护加mappedBy或xml中inverse =true
为什么要用hibernate:
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
Hibernate是如何延迟加载?get与load的区别
1. 对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。
2. Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
这里get和load有两个重要区别:
如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。
总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
说下Hibernate的缓存机制:
一、什么是注解?
解析:来源:Hibernate提供了Hibernate Annotations扩展包,它可以替换复杂的hbm.xml文件( Annotations扩展包是hibernate-annotation-3.4.0GA.zip)
作用:使得Hibernate程序的开发大大的简化。利用注解后,可不用定义持久化类对应的*.hbm.xml,而直接以注解方式写入持久化类的实现中。
二、注解配置持久化类常用注解。
注解 | 含义和作用 |
@Entity | 将 一个类声明为一个持久化类 |
@Id | 声明了持久化类的标识属性(相当于数据表的主键) |
@GeneratedValue | 定义标识属性值的生成策略 |
@Table | 为持久化类映射指定表(table)、目录(catalog)和schema的名称。默认值,持久化类名,不带包名 |
@UniqueConstraint | 定义表的唯一约束 |
@Lob | 表示属性将被持久化为Blob或者Clob类型 |
@Column | 将属性映射到列 |
@Transient | 忽略这些字段和属性,不用持久化到数据库 |
【hibernate】常用注解
转载:https://www.cnblogs.com/yangchongxing/p/10357118.html
目录
========================================================
1、@Entity 实体
2、@Table 表
3、@Id 和 @GeneratedValue 主键及生成策略
4、@Column 列
5、@DynamicInsert 和 @DynamicUpdate 动态字段
6、@Immutable 不变实体
7、@Basic 非空约束
8、@NotNull 非空检查
9、@Access 属性访问
10、@Formula 派生属性
11、@ColumnTransformer 转换列值
12、@Generated 默认值
13、@Temporal 时序属性
14、@CreationTimestamp和@UpdateTimestamp 创建时间戳和更新时间戳
15、@Enumerated 枚举类型
16、@Embeddable 可嵌入组件
17、@Lob 大数据类型
18、@Type 类型适配器
19、@Convert 转换器
20、@MappedSuperclass 不持久化超类属性
21、@AttributeOverrides 和 @AttributeOverride 重写属性
22、@Inheritance 继承策略
========================================================
1、@Entity 实体
声明持久化实体,不带 name 参数时表明和实体名相同,带参数重写表明 @Entity(name="ycx_user")
2、@Table 表
重写表名 @Table(name="ycx_user")
3、@Id 和 @GeneratedValue 主键及生成策略
主键和主键生成策略 @GeneratedValue(generator="id_generator") 或者 @GeneratedValue(strategy=GenerationType.SEQUENCE)
4、@Column 列
name="列名"
table=“列属表名”
nullable=false 不能为空,生成非空约束
length=3 字段长度
insertable=false 不包含 INSERT
updatable=false 不包含 UPDATE
列声明 @Column(name="表明", nullable=false),nullable=false 声明数据库非空约束
5、@DynamicInsert 和 @DynamicUpdate 动态字段
动态 SQL 生成,@DynamicInsert 和 @DynamicUpdate,通过启用动态插入和更新,就可以告知 hibernate 在需要时生成 SQL 字符串
6、@Immutable 不变实体
让实体不可变,这样 hibernate 永远不会执行 update 语句,同时可以进行一些优化,比如对不可变类不进行脏检查。
7、@Basic 非空约束
@Basic(optional=false) 声明数据库非空约束
8、@NotNull 非空检查
@NotNull(message="消息内容"),实体非空注解,但是这个在生成数据库结构时会被忽略,在实体保存校验时起作用。
要想在数据库中生成非空约束,必须结合 @Column(nullable=false) 或者 @Basic(optional=false)
9、@Access 属性访问
重写默认的访问行为,字段访问或者属性访问,已经注解过的实体会从强制的 @Id 注解位置继承访问行为,@Id 在字段上则继承字段访问,在 getter 方法上则继承属性访问。
@Access(AccessType.FIELD) 字段访问
@Access(AccessType.PROPERTY) 属性访问
当 @Access 在实体级别设置则会影响实体的所有访问策略,同样 @Access 也可以重写单个属性的访问策略
若默认是字段访问,在字段上添加 @Access(AccessType.PROPERTY) 则被修改为属性访问
若默认是属性访问,在 getter 方法上添加 @Access(AccessType.FIELD) 则被修改为字段访问
10、@Formula 派生属性
运行时通过 @Formula 估算出来,不会出现在 UPDATE 和 INSERT 中,只会出现在 SELECT 中,可以包含 SQL 函数和子查询。
例如 数据库中没有全名而实体中有 @Formula("concat(firstname,'-',lastname)")
11、@ColumnTransformer 转换列值
数据库中存储重量 weight 单位是克,实体中使用千克
@Column(name="weight") @org.hibernate.annotations.ColumnTransformer(read="weight / 1000",write="? * 1000") protected int kilogramWeight;
12、@Generated 默认值
自动刷新数据库生成的值,如触发器在每次插入和更新后更新的值。使用 @Generated 注解在每次执行 INSERT 和 UPDATE 后委托给 Hibernate 自动查询。
比如插入用户后给一个默认国籍
触发器
BEGIN set new.nationality = 'CN'; END
java
@Column(insertable=false,updatable=false) @org.hibernate.annotations.ColumnDefault("'CN'") //在 Hibernate 导出 SQL 架构 DDL 时设置列的默认值 @org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.INSERT) protected String nationality;
测试
@Test public void testInsert() { this.session.beginTransaction(); User u = new User(); u.setUsername("admin"); u.setFirstname("Tom"); u.setLastname("Green"); u.setKilogramWeight(62); this.session.persist(u); this.session.getTransaction().commit(); //事务提交后才能得到最新的值 System.out.println(u.getId() + " Hibernate 自动刷新数据库触发器生成的值:" + u.getNationality()); assertTrue( true ); }
13、@Temporal 时序属性
JPA 规范要求使用 @Temporal 注解时序属性,以声明所映射列的准确 SQL 数据库类型。当没有提供时 Hibernate 会默认使用 TemporalType.TIMESTAMP。
Java时序类型 java.util.Date;、java.util.Calendar;、java.sql.Date;、java.sql.Time;、java.sql.Timestamp;
TemporalType 选项 DATE、TIME、TIMESTAMP
14、@CreationTimestamp和@UpdateTimestamp 创建时间戳和更新时间戳
当没有提供 @Temporal 时 Hibernate 会默认使用 TemporalType.TIMESTAMP
@Temporal(TemporalType.TIMESTAMP) @Column(updatable=false) @org.hibernate.annotations.CreationTimestamp protected Date createOn; @Temporal(TemporalType.TIMESTAMP) @Column(insertable=false) @org.hibernate.annotations.UpdateTimestamp protected Date updateOn;
当执行插入时 Hibernate 自动给 createOn 赋值,当执行更新时 Hibernate 自动给 updateOn 赋值。
15、@Enumerated 枚举类型
默认 Hibernate 会存储 EnumType.ORDINAL 位置,这种很脆弱。EnumType.STRING 存储枚举值的标签,这样变更不会影响
@Enumerated(EnumType.STRING) private Sex sex;
16、@Embeddable 可嵌入组件
@Embeddable public class Address { @NotNull @Column(nullable=false) protected String street; @NotNull @Column(nullable=false) protected String zipcode; @NotNull @Column(nullable=false) protected String city; public Address() {} public Address(String street,String zipcode,String city) { this.street = street; this.zipcode = zipcode; this.city = city; } @Override public String toString() { return "Address [street=" + street + ", zipcode=" + zipcode + ", city=" + city + "]"; } }
嵌入式组件
protected Address address;
重写嵌入式组件
@AttributeOverrides({ @AttributeOverride(name="street",column=@Column(name="billing_street")), @AttributeOverride(name="zipcode",column=@Column(name="billing_zipcode")), @AttributeOverride(name="city",column=@Column(name="billing_city")) }) protected Address billingAddress;
17、@Lob
二进制数据和大数据
18、@Type 类型适配器
@org.hibernate.annotations.Type(type="yes_no") protected boolean verify;
@org.hibernate.annotations.Type(type="true_false") protected boolean verify;
19、@Convert 转换器
@Convert(converter = MoneyConverter.class,disableConversion=false) protected Money money;
20、@MappedSuperclass 不持久化超类属性
使用 @Entity 映射具体类,要想超类的属性被忽略并且不持久化,则必须使用 @MappedSuperclass
21、@AttributeOverrides 和 @AttributeOverride 重写属性
子类重写从父类继承的字段和属性
类重写嵌入式字段和属性
22、@Inheritance 继承策略
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 每个带有联合的具体类使用一个表
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 每个类层次结构使用一个表
@Inheritance(strategy=InheritanceType.JOINED)
=====================================================================================================
Hibernate常用查询方式
hibernate的查询方式常见的主要分为三种: HQL, QBC(命名查询), 以及使用原生SQL查询(SqlQuery)
一、HQL查询
• HQL(Hibernate Query Language)提供了丰富灵活的查询方式,使用HQL进行查询也是Hibernate官方推荐使用的查询方式。
• HQL在语法结构上和SQL语句十分的相同,所以可以很快的上手进行使用。使用HQL需要用到Hibernate中的Query对象,该对象专门执行HQL方式的操作。
查询所有示例
-
session.beginTransaction();
-
String hql = "from User"; // from 后跟的是要查询的对象,而不是表
-
Query query = session.createQuery(hql);
-
List<User> userList = query.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
带where的查询示例
-
session.beginTransaction();
-
String hql = "from User where userName = 'James'";
-
Query query = session.createQuery(hql);
-
List<User> userList = query.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
-
/*
-
在HQL中where语句中使用的是持久化对象的属性名,如上面示例中的userName。当然在HQL中也可以使用别名
-
*/
-
String hql = "from User as u where u.userName = 'James'";
-
/*
-
过滤条件
-
在where语句中还可以使用各种过滤条件,如:=、<>、<、>、>=、<=、between、not between、
-
in、not in、is、like、and、or等
-
*/
获取一个不完整的对象
-
session.beginTransaction();
-
String hql = "select userName from User";
-
Query query = session.createQuery(hql);
-
List<Object> nameList = query.list();
-
for(Object obj:nameList){
-
String name=(String)obj;
-
System.out.println(name);
-
}
-
session.getTransaction().commit();
-
// 多个属性的话,需要用object[]接收
-
session.beginTransaction();
-
String hql = "select userName,userPwd from User";
-
Query query = session.createQuery(hql);
-
List nameList = query.list();
-
for(Object obj:nameList){
-
Object[] array = (Object[]) obj; // 转成object[]
-
System.out.println("name:" + array[0]);
-
System.out.println("pwd:" + array[1]);
-
}
-
session.getTransaction().commit();
统计和分组查询
-
session.beginTransaction();
-
String hql = "select count(*),max(id) from User";
-
Query query = session.createQuery(hql);
-
List nameList = query.list();
-
for(Object obj:nameList){
-
Object[] array = (Object[]) obj;
-
System.out.println("count:" + array[0]);
-
System.out.println("max:" + array[1]);
-
}
-
session.getTransaction().commit();
-
/*
-
该条sql语句返回的是单条数据,所以还可以这样写
-
单列数据用Object,多列数据用Object[]
-
*/
-
Object[] object = (Object[]) query.uniqueResult();
-
System.out.println("count:" + object[0]);
-
System.out.println("max:" + object[1]);
更多写法
-
select distinct name from Student;
-
select max(age) from Student;
-
select count(age),age from Student group by age;
-
from Student order by age;
HQL占位符
-
session.beginTransaction();
-
String hql = "from User where userName = ?";
-
Query query = session.createQuery(hql);
-
// 索引从0开始
-
query.setString(0, "James");
-
List<User> userList = query.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
HQL引用占位符
-
-
session.beginTransaction();
-
String hql = "from User where userName = :name";
-
Query query = session.createQuery(hql);
-
query.setParameter("name", "James");
-
List<User> userList = query.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
HQL分页
-
session.beginTransaction();
-
String hql = "from User";
-
Query query = session.createQuery(hql);
-
query.setFirstResult(0);
-
query.setMaxResults(2);
-
List<User> userList = query.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
二、QBC(Query By Criteria)查询
• Criteria对象提供了一种面向对象的方式查询数据库。Criteria对象需要使用Session对象来获得。
• 一个Criteria对象表示对一个持久化类的查询。
查询所有
-
session.beginTransaction();
-
Criteria c = session.createCriteria(User.class);
-
List<User> userList = c.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
where
-
session.beginTransaction();
-
Criteria c = session.createCriteria(User.class);
-
c.add(Restrictions.eq("userName", "James"));
-
List<User> userList = c.list();
-
for(User user:userList){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
Restrictions对象
-
方法名称 对应SQL中的表达式
-
----------------------------------------------------------
-
Restrictions.eq field = value
-
Restrictions.gt field > value
-
Restrictions.lt field < value
-
Restrictions.ge field >= value
-
Restrictions.le field <= value
-
Restrictions.between field between value1 and value2
-
Restrictions.in field in(…)
-
Restrictions.and and
-
Restrictions.or or
-
Restrictions.like field like value
-
示例
-
Criteria c = session.createCriteria(User.class);
-
c.add(Restrictions.like("userName", "J"));
-
c.add(Restrictions.eq("id", 120));
-
c.add(Restrictions.or(Restrictions.eq("userName", "James"),
-
Restrictions.eq("userName", "Alex")));
获取唯一记录
-
session.beginTransaction();
-
Criteria c = session.createCriteria(User.class);
-
c.add(Restrictions.eq("id", 120));
-
User user = (User) c.uniqueResult();
-
System.out.println(user.getUserName());
-
session.getTransaction().commit();
分页
-
Criteria c = session.createCriteria(User.class);
-
c.setFirstResult(0);
-
c.setMaxResults(5);
分组与统计
-
session.beginTransaction();
-
Criteria c = session.createCriteria(User.class);
-
c.setProjection(Projections.sum("id"));
-
Object obj = c.uniqueResult();
-
System.out.println(obj);
-
session.getTransaction().commit();
Projections对象
-
方法名称 描述
-
-------------------------------------------------------
-
Projections.sum 等于SQL中聚合函数sum
-
Projections.avg 等于SQL中聚合函数avg
-
Projections.count 等于SQL中聚合函数count
-
Projections .distinct 去除重复记录
-
Projections.max 等于SQL中聚合函数max
-
Projections.min 等于SQL中聚合函数min
-
Projections .groupProperty 对指定的属性进行分组查询
多个统计与分组
-
session.beginTransaction();
-
Criteria c = session.createCriteria(User.class);
-
ProjectionList projectionList = Projections.projectionList();
-
projectionList.add(Projections.sum("id"));
-
projectionList.add(Projections.min("id"));
-
c.setProjection(projectionList);
-
// 和HQL一样,单列用Object,多列用Object[]
-
Object[] obj = (Object[]) c.uniqueResult();
-
System.out.println("sum:" + obj[0]);
-
System.out.println("min:" + obj[1]);
排序
-
Criteria c = session.createCriteria(User.class);
-
c.addOrder(Order.desc("id"));
三、原生SQL查询:
示例
-
session.beginTransaction();
-
String sql = "select id,username,userpwd from t_user";
-
List list = session.createSQLQuery(sql).list();
-
for(Object item : list){
-
Object[] rows = (Object[]) item;
-
System.out.println("id:" + rows[0] + "username:"
-
+ rows[1] + "userpwd:" + rows[2]);
-
}
-
session.getTransaction().commit();
addEntity()示例
-
session.beginTransaction();
-
String sql = "select id,username,userpwd from t_user";
-
// addEntity()可以告诉Hibernate你想要封装成对象的类型,然后自动为你封装
-
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
-
List<User> list = query.list();
-
for(User user : list){
-
System.out.println(user.getUserName());
-
}
-
session.getTransaction().commit();
uniqueResult示例
-
session.beginTransaction();
-
String sql = "select id,username,userpwd from t_user where id = 2";
-
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
-
User user = (User) query.uniqueResult();
-
System.out.println(user.getUserName());
-
session.getTransaction().commit();
转载地址:https://blog.csdn.net/u010963948/article/details/16818043