一 创建项目
-
用
image.pngidea
创建一个hibernate项目。
-
参考https://blog.csdn.net/qq_29216083/article/details/70194056。通过表自动生成实体类和配置文件
-
添加junit,参考:https://blog.csdn.net/traitor_4/article/details/80168695
二 配置介绍
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateds?useUnicode=true&characterEncoding=utf-8</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="com.zyc.UserEntity"/>
<mapping resource="com/zyc/UserEntity.hbm.xml"/>
<!-- <property name="connection.username"/> -->
<!-- <property name="connection.password"/> -->
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>
cfg.xml和.hbm.xml的区别
- hibernate.cfg.xml 配置文件提供链接数据库的基本信息
账号 密码 驱动 数据库ip 端口 - Product.hbm.xml 提供对象与表的映射关系
对应哪个表? 什么属性,对应什么字段
三 CRUD
插入
@Test
public void batchInsert(){
for (int i = 0; i < 10; i++) {
UserEntity user = new UserEntity();
user.setId(i+1);
user.setName("李维民"+i);
user.setAge(45+i);
user.setAdress("广东");
user.setMobile("1101"+i);
session.save(user);
}
}
对象状态
实体类对象在Hibernate中有3种状态:分别是瞬时,持久和脱管
- 瞬时 指的是没有和hibernate发生任何关系,在数据库中也没有对应的记录,一旦JVM结束,这个对象也就消失了
- 持久 指得是一个对象和hibernate发生联系,有对应的session,并且在数据库中有对应的一条记录
- 脱管 指的是一个对象虽然在数据库中有对应的一条记录,但是它所对应的session已经关闭了
查询
@Test
public void get(){
UserEntity user = session.get(UserEntity.class,2);
UserEntity user2 = (UserEntity) session.load(UserEntity.class, 3);
System.out.println(user.getAge());
System.out.println(user2.getAge());
}
//执行输出
//Hibernate: select userentity0_...
//46
//Hibernate: select userentity0_...
//47
注意
不要用debug去执行,因为debug时可以看到对象属性值,所以看不到延迟加载的现象
load和get的区别
- load方式是延迟加载,只有属性被访问的时候才会调用sql语句;get方式是非延迟加载,无论后面的代码是否会访问到属性,马上执行sql语句
- id不存在时。get方式会返回null ;load方式会抛出异常
删除
@Test
public void delete(){
UserEntity user = session.get(UserEntity.class,8);
System.out.println(user);
session.delete(user);
}
修改
@Test
public void update(){
UserEntity user = session.get(UserEntity.class,9);
user.setAdress("东山");
session.update(user);
}
四 查询方式
hql
HQL(Hibernate Query Language)是hibernate专门用于查询数据的语句,有别于SQL,HQL 更接近于面向对象
的思维方式。
@Test
public void hql(){
String hql ="from UserEntity where id>3";
Query query = session.createQuery(hql);
List<UserEntity> list= query.list();
for(UserEntity user:list){
System.out.println(user.getId());
}
}
Criteria
与HQL和SQL的区别是Criteria 完全是 面向对象的方式在进行数据查询,将不再看到有sql语句的痕迹
查询步骤
- 通过session的createCriteria创建一个Criteria 对象
- Criteria.add 增加约束。 在本例中增加一个对name的模糊查询(like)
- 调用list()方法返回查询结果的集合
在hibernate5.10版本中已经不推荐该种方式了。参考:https://blog.csdn.net/blue__fisher/article/details/78885143
@Test
public void criteria(){
Criteria criteria = session.createCriteria(UserEntity.class);
criteria.add(Restrictions.gt("id",2));
criteria.add(Restrictions.eq("adress","东山"));
List<UserEntity> list= criteria.list();
for(UserEntity user:list){
System.out.println(user.getId());
}
}
标准sql
@Test
public void sql(){
String sql = "select * from user where name like '%李维民3%'";
Query q= session.createSQLQuery(sql);
List<Object[]> list= q.list();
for (Object[] os : list) {
for (Object filed: os) {
System.out.print(filed+"\t");
}
System.out.println();
}
}
//自己常用的方式,转成一个map
@SuppressWarnings("unchecked")
List<Map<String,Object>> zslist = (List<Map<String,Object>>)baseDao.sqlQuery(zssql)
.addScalar("id",StandardBasicTypes.STRING)
.addScalar("parentId",StandardBasicTypes.STRING)
.addScalar("name",StandardBasicTypes.STRING)
.addScalar("zs",StandardBasicTypes.INTEGER)
.addScalar("bmd",StandardBasicTypes.INTEGER)
.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
五 关系
xml配置
- [xml配置版]双向一对多和双向多对多、级联、inverse:https://www.cnblogs.com/gdwkong/p/8337081.html
- [xml配置版]单向多对一、单向一对多、双向一对多:https://blog.csdn.net/qq_36748278/article/details/78035244
- [xml配置版]一对一关系映射详解:https://www.cnblogs.com/whgk/p/6128395.html
注解版
https://www.cnblogs.com/printN/p/6408818.html
六 注解
主键生成注解
@Id
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.AUTO)
@Id
@Column(name = "id")
@GeneratedValue(generator = "uuidGener")
@GenericGenerator(name = "uuidGener", strategy="uuid")
参考:https://blog.csdn.net/qq193423571/article/details/76371372
集合映射,关联关系映射
参考:https://blog.csdn.net/qq_29829081/article/details/51055535
联合主键、继承映射
参考:
- [注解版]https://blog.csdn.net/qq_29829081/article/details/51054998
- [配置文件版]https://blog.csdn.net/sinat_35821285/article/details/78611652
@MappedSuperclass
参考:https://www.cnblogs.com/zqyanywn/p/7753596.html
七 个人理解
7.1 关系注解和级联的关系?
我认为关系注解和级联是两个独立的概念,但级联时的部分行为又和关系有关。
-
关系注解
:个人认为主要是便于orm框架在查询
时,发现对象和对象是关联关系。告诉orm框架如何将两个有关联的对象(数据库中就是不同表之间的记录
)直接一起查询并组合起来,减少程序员的开发工作 -
级联
:有级联更新、删除等等。也是为了减少代码,让多个有关联的对象在持久化其中一个时,连带着把其他的也一起持久化。
7.2 更新级联时的行为特点?
- 当我们使用关系注解时。默认级联关系是
none
.即不会级联保存。 - 只有当我们设置了级联关系,orm框架才会帮我级联操作
-
hibernate为了保证每次更新的级联不出错,会先将之前所有关联的记录的关联字段设置为null
image.png
7.3 开启了级联就一定会级联吗?
是!
但关系能否正确映射到数据库就不一定了!!!
这主要看你开启了级联的一方是否维护关系
,如果不维护。那关系就不会正确的映射到数据库中
7.4 一对多由哪一方维护?
个人经验:还是由一的一方维护比较方便。
虽然大部分教学视频里都说双向一对多时
,由一的一方维护关系会减少不必要的sql
(这个结论时对的)。但我在实际开发中发现,由一的一方维护有个优点
:我们只需要将多的一方放入或移出集合,就可以控制两方是否有关联(这个还是方便啊
)
7.5 @JoinColumn注解啥情况?
在一对多关系中,无论注解在哪。name对应的列肯定在多的一方。不写,hibernate还会生成中间表
在一对一关系中,注解在哪个类中,name对应的列就在该类对应的表中
7.5 @ElementCollection
该注解如果和@Embedded修饰的类结合使用。那么@Embedded修饰的类对应的表就没有主键。每次我们更新
时(保存不用,第一次插入删空气吗?),外面那个类时,都会把之前所有集合表中有关的记录删除,重新插入一份。
7.6 外键维护和级联也是两个独立的概念
只要记住,只要不是显示的用了inverse(再注解中对应mappedby)
的一方,hibernate都会维护外键关系
参考
网友评论