对比的写一下这两者的使用吧
1.“hello world”之简单运行流程
configuration类,负责管理hibernate的配置信息。包括如下内容:hibernate运行的底层信息,数据库url、用户名、密码、jdbc驱动类,数据库方言,数据库连接池等持久化类与数据表的映射关系
创建configuration的两种方式
属性文件
1.configuration cfg=new Configuration();
xml文件
2.configuration cfg=new configuration().configure();
schemaExport类
schemaExport 类主要负责根据类或则hbm文件映射生成持久化类对应的表结构
创建schemaExport的方式
schemaExport schema=new SchemaExport(config);
sessionfactory对象的创建
configuration对象根据当前的配置信息生成sessionfactory对象。sessionfactory对象一旦构造完毕,即被赋予特定的配置信息,是线程安全的,构造sessionfactory很消耗资源,一般情况下一个应用中只初始化一个sessionfactory对象。
session对象
session是应用程序与数据库之间交互操作的一个单线程对象,是hibernate运作的中性,所有持久化对象必须在session的管理下可以进行持久化操作。此对象的生命周期很短,session对象有一个一级缓存,显式执行flush之前,所有的持久层操作数据都缓存在session对象处。是线程不安全的
transaction
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
Transaction tx=session.beginTransaction();
public static void main(String[] args) throws Exception{
// 1. 加载默认的hibernate.cfg.xml的配置文件
Configuration config = new Configuration().configure();
ps:如果加载指定名称的配置文件使用的方式是Configuration cfg = new Configuration()
.configure(“myhibernate.cfg.xml”);
// 2. 加载hbm文件 (Test.hbm.xml),此处是加载需要使用到的映射文件与类,写法可以简写成Test.class
config.addClass(com.gudai.hibernate.api.Test.class);
// 3. 根据配置生成表
SchemaExport schema = new SchemaExport(config);
schema.create(true, true);
// 4. 构建SessionFactory对象
SessionFactory factory = config.buildSessionFactory();
Session session = factory.openSession(); // 5. 建立连接
Transaction tran = session.beginTransaction(); // 6. 开启事务
Test t = new Test();
t.setName("test hibbernate");
session.save(t);
tran.commit(); // 7. 提交事务
session.close(); // 8. 关闭会话
}
分配置文件
<hibernate-mapping package="cn.gudai.mapper">
<class name="ClassContent" table="teach_classcontent">
<id name="id">
<generator class="native" />
</id>
<property name="content" type="string"/>
<property name="img" type="string"/>
<property name="video" type="string"/>
<property name="date" type="date"/>
<property name="type" type="int"></property>
<!-- 多对一,多门课程内容对应一门课程 -->
<many-to-one name="bclass" class="TeachClass" column="class_id" cascade="delete"> </many-to-one>
</class>
</hibernate-mapping>
总的配置文件
<hibernate-configuration>
<session-factory>
<!-- 数据库信息(连接信息写到spring的配置文件中)作用是切换数据库的作用 -->
<property name="dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<!-- 其他配置 -->
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- 导入映射配置 -->
<mapping resource="cn/gudai/mapper/TeachClass.hbm.xml" />
<mapping resource="cn/gudai/mapper/User.hbm.xml" />
<mapping resource="cn/gudai/mapper/ClassContent.hbm.xml" />
<mapping resource="cn/gudai/mapper/LearingResult.hbm.xml" />
<mapping resource="cn/gudai/mapper/ClassResource.hbm.xml" />
<mapping resource="cn/gudai/mapper/QuestionAndAnswer.hbm.xml" />
</session-factory>
</hibernate-configuration>
其执行流程如下
1.应用程序先调用configuration类,该类读取hibernate配置文件及映射文件中信息
2.并用这些信息生成一个sessionfactory对象
3.然后从sessionfactory对象生成一个session对象
4.并用session对象生成transaction对象
session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对po进行加载、保存、更新、删除、等操作;
ps: Get()如果没有找到持久化类返回null,有可能导致空指针异常
Load()如果没有找到持久类直接抛出异常
get()是直接加载数据,load()是延迟加载,当使用被加载数据的时候才发送sql.简而言之:hibernate对于load认为数据库一定存在,因此可以放心的使用代理进行延迟加载,如果使用中发现问题,那么只能抛出异常,而对于get方法一定要获取真实的数据,否则返回null
在查询的情况下,可通过session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,transaction对象将提交这下操作到数据库中。
mybatis中
mybatis是一个持久层的框架,让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成满足sql语句。mybatis可以preparedstatement中的输入参数自动进行输入映射,将查询结果灵活映射成java对象(输出映射)
sqlmapconfig.xml
配置mybatis的运行环境,数据源,事务
<configuration>
<enviroments default="development">
<transactionManage type="JDBC"/>
<datSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306...">
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</enviroments>
</configuration>
User.xml
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="com.gudai.pojo.User">
select * from user where id=#{id}
</select>
</mapper>
<mappers>
<mapper resource="sqlmap/User.xml"/>
<mappers>
测试文件类
public void findUserByIdTest() throws Exception{
//mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream=Resource.getResourceAsStream(resource);
//创建会话工厂得到sqlsession
SqlSession sqlSession=sqlSessionFactory.openSession();
//第一个参数namespace加id名
User user=sqlSession.selectOne("test.findUserById",1);
System.out.println(user);
//释放资源
sqlSession.close();
}
接口开发方式
xml中的
namespace为mapper.java的全限定名
id为接口的方法名
resultType为其返回的值类型
2.映射关系
一对多:
Teacher.class
private Set<Student> students=new HashSet<Student>();
Student.class
private Teacher teacher;
xml配置文件
老师的写法
<set name="students" inverse="true">
<key column="teacher_id"></key>
<one-to-many class="com.gudai.Student"/>
</set>
ps:可在set标签上加上lazy="false"关闭懒加载
学生的写法
<many-to-one name="teacher" class="com.gudai.Teacher" column="teacher_id"></many-to-one>
注意:懒加载在这种关系映射是都存在的(一对多)
一对一:
public class Person{
private Card card;
}
public class Card{
private Person person;
}
person的映射文件
<one-to-one name="card" class="com.gudai.Card"/>
card的映射文件
<many-to-one name="person" class="com.gudai.Person" column="user_id" unique="true"></many-to-one>
多对多的映射
public class User{
private Set<Role> roles=new HashSet<Role>();
}
public class Role{
private Set<User> users=new HashSet<User>();
}
user的映射文件
<set name="roles" table="user_role" cascade="save-update">
<key column="user_id"></key>
<many-to-many class="com.gudai.Role" column="role_id"></many-to-many>
</set>
role的映射文件
<set name="users" table="user_role" inverse="true">
<key column="role_id"></key>
<many-to-many class="com.gudai.User" column="user_id"></many-to-many>
</set>
mybatis中
一对一:
public class OrdersCustom extends Orders{
private String username;
private String sex;
private String address;
}
查询的映射文件
mapper.xml
<select id="findOrdersUser" resultType="com.gudai.OrdersCutom">
select orders.*,user.username,user.sex,user.address from orders,user where orders.user_id=user.id
</select>
ps:以上的方法是po中成员变量是所有的对应数据库的元素字段名相同
附加resultmap的实现同样的sql结果
使用resultMap映射的思路,是哟个resultMap将结果中订单信息映射到orders对象中,在orders类中添加user属性,将关联查询出来的用户信息映射到orders对象的user属性中。
需要orders类中添加user属性
public class Orders{
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//用户信息
private User user;
}
Mapper.xml定义resultMap
<resultMap type="cn.gudai.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
column:订单信息的唯 一标识 列
property:订单信息的唯 一标识 列所映射到Orders中哪个属性
-->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property=note/>
<!-- 配置映射的关联的用户信息 -->
<!-- association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<association property="user" javaType="cn.gudai.mybatis.po.User">
<!-- id:关联查询用户的唯 一标识
column:指定唯 一标识用户信息的列
javaType:映射到user的哪个属性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
statement定义
<select id="findOrdersUserReusltMap" resultMap="OrdersUserResultMap">
select order.*,user.username,user.sex,user.address from orders,user where orders.user_id=user.id
</select>
mapper.java
//查询订单关联查询用户使用resultMap
public List<Orders> findOrdersUserResultMap() throws Exception;
ps:建议使用resultType,resultMap可以实现延迟加载,resultType无法实现延迟加载。
一对多(一个订单-------对应-----多个订单明细)
在orders中添加list订单明细属性
public class Orders{
//订单明细
private List<Orderdetail> orderdetails;
}
mapper.xml
查询订单关联查询用户及订单明细,使用resultMap
<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDeatailResultMap">
select orders.*,user.username,user.sex,user.address,orderdetail.items_id,orderdetail.items_num,
orderdetail.orders_id from orders,user,orderdetail where order.user_id=user.id and orderdetail.orders_id=ordersid
</select>
resultMap定义
订单及订单明细的resultMap,使用extends继承,不用在配置中写订单信息和用户信息的映射
<resultMap type="com.gudai.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
<!--使用extends继承,不用在配置订单信息和用户信息的映射-->
订单明细信息
一个订单关联查询出了多条明细,要使用collection进行映射
collection:对关联查询到多条记录映射到集合对象中
property:将关联查询到多条记录映射到cn.gudai.mybatis.po.Orders哪个属性
ofType:指定映射到list集合属性中pojo的类型
-->
<collection property="orderdetails" ofType="cn.gudai.mybatis.po.Orderdetail">
<!-- id:订单明细唯 一标识
property:要将订单明细的唯 一标识 映射到cn.gudai.mybatis.po.Orderdetail的哪个属性
-->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
</collection>
</resultMap>
</resultMap>
ps:此处如果使用resultType则会出现冗余数据,需要使用双重for循环减少冗余的数据
多对多
user-orders 一对多
orders-orderDetail 一对多
orderDetail-items 一对多
mapper.xml文件
<!--查询用户及购买的商品信息,使用resultMap
-->
<select id="findUserAndItemsResultMap" resultMap="UserAndItemssResultMap">
select orders.*,user.username,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.items_num,orderdetail.orders_id,items.name items_name,items.detail items_detail,items.price items_price
from orders,user,orderdetail,items where orders.user_id=user.id and orderdetail.orders_id=orders.id and orderdetail.items_id=items.id
</select>
resultMap定义
查询用户及购买的商品
<resultMap type="com.gudai.User" id="UserAndItemsResultMap">
<!--用户信息-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 订单信息
一个用户对应多个订单,使用collection映射
-->
<collection property="ordersList" ofType="cn.gudai.mybatis.po.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 订单明细
一个订单包括 多个明细
-->
<collection property="orderdetails" ofType="cn.gudai.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
<!-- 商品信息
一个订单明细对应一个商品
-->
<association property="items" javaType="cn.gudai.mybatis.po.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="items_detail" property="detail"/>
<result column="items_price" property="price"/>
</association>
</collection>
</collection>
</resultMap>
</resultMap>
3.crud
hibernate中
添加
session.save(emp);
ps:其中emp为一个对象
删除(一定是开启事物的)
// 先根据id查询对象,再判断删除
Object obj = session.get(Employee.class, id);
if (obj != null) {
session.delete(obj);
}
更新
session.update(emp);
ps:其中emp为一个对象
查询
**oid方式**
get方式(可能报空指针异常)
session.get(Employee.class,id)
load方式(认为数据一定是存在的,否在会抛异常)
session.load(Employee.class,id)
**hql方式**(From类as c where,半面向对象的方式)
1.查询全部
Query q1=session.createQuery("from cursomter");
2.排序查询
q1=session.createQuery("from curtomer as c order by c.age desc");
3.指定列查询
q1=session.createQuery("select c.name.c.age from Customer as c order by c.age desc");
List list2=q1.list();//查询的集合
4.指定列封装查询
q1=session.createQuery("select new Customer(c.name,c.age) from Customer as c order by c.age desc");
5.条件查询
q1=session.createQuery("from Curtomer c where c.age>:age").setInteger("age",40);
q1=session.createQuery("from Customer c where c.age>:age and c.name=:name").setInteger("age",40).setString("name","王武");
ps:另一种指定参数的方式是
Query q =session.createQuery("from Employee where empName=?");
// 注意:参数索引从0开始
q.setParameter(0, employeeName);
注意:这种写法q.setString(0, "%部%");
6.单行查询对象查询
Object obj1=session.createQuery("from Curtomer c where c.age>:age and c.name=:name").setInteger("age",40).setString("name","王武").uniqueResult();
ps:分页查询
setFirstResult();//查询的实际行所在行
setMaxResults();//查询返回的行数
7.使用本地sql查询
SQLQuery q = session.createSQLQuery("SELECT * FROM t_Dept limit 5;")
.addEntity(Dept.class); // 也可以自动封装
System.out.println(q.list());
mybatis中
xml开发方式下的crud
添加
<insert id="insertUser" parameterType="com.gudai.User">
insert into user(username,birthday,sex,address) value(#{useranem},#{birthday})
</insert>
java代码书写是
String resource="SqlMapConfig.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactory().builder(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
//第一个参数:命名namespace的名称+id
//第二参数:要添加的用户
sqlSession.insert("test.insertUser",user);
删除
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
ps:这里的int是使用了别名,其实是Integer类型
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.
MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
更新用户
映射文件
<update id="updateUser" parameterType="com.gudai.User">
update user set username=#{username} where id="#{id}"
</update>
ps:如果传入的参数是一个对象则可以直接从对象中获取要设置的字段名称,前提是这个对象包含有字段名称
查询
<select id="findUserByName" parameterType="string" resultType="com.gudai.User">
select * from user where username like '%${value}%'
</select>
java代码
String resource="SqlMapConfig.xml";
InputStream inputStream=Resource.getResouecesAsInputStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
sqlSession.selectList("test.findUserByName","小明");
//查询单个使用selectOne();
4.事务
hibernate中
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作
Transaction tx=session.beginTransaction();
tx.commit();//提交事务
mybatis中
默认是开启事务的
sqlSession.commit();
5.缓存
一级缓存
hibernate中
session缓存,hibernate的一级缓存是由session提供的,因此它存在于session整个生命周期中。当程序调用crud方法时,如果session中不存在该对象,那么会先将本次的对象存储到一级缓存中便于以后使用,当session关闭的同时清空一级缓存数据。clear()/evict()
作用:减少访问数据的次数,进而提交效率。保证缓存中的对象与数据库的记录保持同步,当缓存的对象该
ps:当一个实体对象被两个session关联时,当其中一个session更新,另一个session所关联的对象也跟则更新
mybatis中
mybatis提供一级缓存,一级缓存是sqlSession级别的缓存。不同的sqlSession之间的缓存数据区域(hashMap)是互相不影响的。
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。如果sqlSession去执行commit操作(执行插入、更行、删除),清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储的是更新的信息,避免站都。第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
ps:Mybatis默认支持一级缓存,不需要再配置文件去配置,
同时如果sqlSession关闭,一级缓存就清空
注意:实际开发过程中事务的控制是在service层实现的
二级缓存
hibenate中
Hibernate中提供的第二级缓存指的是sessionfactory缓存,是支持可插拔式的缓存。该缓存主要是由sessionFactory进行管理。由于sessionFactory的生命周期是整个应用的进程,因此这个缓存中存储的是对象散列数据,第二级缓存是可选的,可以在每一个类或集合上进行细粒度的控制。
方法一:默认的缓存框架的开启
<!--****************** 【二级缓存配置】****************** -->
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="com.gudai.b_second_cache.Dept"/>
<class-cache usage="read-only" class="com.gudai.b_second_cache.Employee"/>
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="com.gudai.b_second_cache.Dept.emps"/>
方法二:使用ehcache缓存框架开启缓存
开启的缓存在类中与集合的方式如下
<class name="com.gudai.Memeber" table="member">
...
<!--在类中添加如下标签是开启类中的缓存-->
<cache usage="read-write"/>
...
<set name="members" >
...
<!--在集合添加如下标签是开发集合形式的二级缓存-->
<cache usage="read-write"/>
...
</set>
</class>
ehcache.xml配置文件(此配置文件是在src目录下实现的)
<?xml version="1.0" encoding="utf-8"?>
<ehcache>
<diskStore path="c:/ehcache"/>
<defaultCache maxElementsInMemory="200" eternal="false"
timeToIdleSeconds="40" timeToLiveSeconds="60"
overflowToDisk="true"/>
<cache name="cn.itcast.hibernate.ehcache.Member"
maxElementsInMemory="200" eternal="false"
timeToIdleSeconds="40" timeToLiveSeconds="60"
overflowToDisk="true"/>
</ehcache>
此方法需要导入的jar包是:
mybatis中
开启二级缓存
sqlSession去查询用户id为1的用户信息,查询到用户信息将会查询数据存储到二级缓存中。如果sqlSession3执行相同mapper下sql,执行commit提交,清空mapper下的二级缓存区域的数据。sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取数据。二级缓存与一级缓存区别,二级缓存的范围更大,多大sqlSession可以共享一个userMapper的二级缓存区域。UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)每一个namespace的mapper都有一个二级缓存区域,两个mapper的namepsace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
开启二级缓存
mybatis的二级缓存是mapper范围级别,除了在sqlMapConfig.xml设置二级缓存的总开关,还要具体mapper.xml中开启二级缓存。
在核心配置文件sqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
在相应的mapper.xml的配置文件下加上
开启本mapper的namespace下的二级缓存
<cache/>
注意:调用的pojo类实现序列化接口
public class User implements Serializable{
...
}
为了将缓存数据去取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样的内存。
ps:确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自 不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况 下就要用到对象的序列化。
只有序列化的对象才可以存储在存储设备上。为了对象的序列化而需要继承的接口也只是一个象征性的接口而已,也就是说继承这个接口说明这个对象可以 被序列化了,没有其他的目的。之所以需要对象序列化,是因为有时候对象需要在网络上传输,传输的时候需要这种序列化处理,从服务器硬盘上把序列化的对象取 出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行相应的处理。
在查询的时候禁用缓存
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false"/>
总结:针对每次查询都需要最新数据sql,要设置成userCache=false,禁用二级缓存。
以上情况无法适应分布式二级缓存
6.延迟加载
hibernate中
延迟加载存在于
一对一
一对多
多对多
中
默认是存在
解决懒加载异常是http://745761505.blog.51cto.com/9241055/1538735
mybatis中
resultMap具备延迟加载功能
延迟加载resultMap
使用association中的select指定延迟加载去执行的statement的id
<!-- 延迟加载的resultMap -->
<resultMap type="cn.gudai.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
<!--对订单信息进行映射配置 -->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 实现对用户信息进行延迟加载
select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)
要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace
column:订单信息中关联用户信息查询的列,是user_id
关联查询的sql理解为:
SELECT orders.*,
(SELECT username FROM USER WHERE orders.user_id = user.id)username,
(SELECT sex FROM USER WHERE orders.user_id = user.id)sex
FROM orders
-->
<association property="user" javaType="cn.gudai.mybatis.po.User"
select="cn.gudai.mybatis.mapper.UserMapper.findUserById" column="user_id">
<!-- 实现对用户信息进行延迟加载 -->
</association>
</resultMap>
在sqlMapconfig.xml中配置开启延迟加载
<settings>
<!-- 打开延迟加载 的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
hibernate使用过程记录
Hibernate中的session的缓存是共享的(即一级缓存是共享的)
Xml文件中配置属性字段唯一书写
当我们想要一个字段唯一可以使用unique(唯一)属性设置在property上或者使用unique-key(唯一且不为空),当我们的数据库表已经创建完成后则添加此unique的属性是不会起到任何的作用的,除了not null其它的属性只有在数据库ddl(包括创建表修改表)语言中起作用。
Xml配置中没有可以使用default属性为某个字段添加默认值
可以在某字段上附上初始值为多少
关于默认值的设定
1)<property>元素 insert属性:设置为false,在insert语句中不包含这个字段,表示永远不会被插入,默认true
2)<property>元素 update属性:设置为false,在update语句中不包含这个字段,表示永远不会被修改,默认true
3)<class>元素 mutable属性:设置为false就是把所有的<property>元素的update属性设置为了false,说明这个对象不会被更新,默认true
4)<property>元素 dynamic-insert属性:设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false
5)<property>元素 dynamic-update属性,设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中,默认false
6)<class>元素 dynamic-insert属性:设置为true,表示把所有的<property>元素的dynamic-insert属性设置为true,默认false
7)<class>元素 dynamic-update属性:设置为true,表示把所有的<property>元素的dynamic-update属性设置为true,默认false
Cascade与inverse的理解
个人对cascade的理解
Cascade是当主对象进行某种操作是否对其关联对象的从对象也做类似的操作。
Inverse的理解是是否放弃维护关联关系(true表示不维护关联关系,false表示该对象维护关联关系)。在one-to-many维护关联关系就是更新外键。Many-to-many维护关联关系
就是在中间表增减记录。默认的情况下是false。
Hibernate中的保存的使用(save)
Session.save(user)的方法它是需要开启事务的
可以使用hql语句去实现以下操作
Hibernate中的删除的使用(delete)
Hibernate中的更新的使用(update)
Hibernate中使用查询(select)
但是级联的删除只能使用对象的delete即session.delete(user);注意:它必须开启事务才可以实现删除的操作。(会报外键错误)