写在前面的,很常用,现解释如下
hibernate.cfg.xml为hibernate的核心配置文件
sessionFactory 为session工厂,对应数据库的配置和连接信息
session 指的是和数据库的一次会话(connection)
1.
<property name="gname" column="gname"></property>
<!-- column对应数据库中的字段,可不写 ,默认值为属性名-->
2.session.evict(obj)会将指定的对象从session缓存中清除。
session.clear():会把缓冲区的全部对象清除,但不包括操作中的对象。
3.映射文件中,<column name="myGrade_id">表示外键。
4.ThreadLocal是为了解决多线程的并发问题而设计,把数据和线程绑定起来,无需加锁。为了减少冲突,给每一个请求都分配一个通道。类似于存储东西的盒子,牺牲空间来减少时间的消耗。比如使用ThreadLocal后,把一个对象存入A线程,在B线程中查找对象的属性,则找不到。
Thread并不是一个thread,而是thread的局部变量。
5.inverse常用在一对多双向关联关系中,表示是否放弃外键维护权,true表示放弃,false表示不放弃。在一对多的表中,inverse只能用在one的这一方。即在一的这一方设置inverse=true,表示将主外键的关系交由多方来维护。这是为了节约数据库资源,打个比方,在一个公司,是所有员工认识老板容易,还是老板认识所有员工容易?
inverse属性的作用为是否将集合对象的修改反映到数据库中,inverse的默认值为false,表示将集合对象的修改反映到数据库中,inverse=false的为主动方,由主动方负责维护关联关系。inverse=true,表示对集合对象的修改不会被反映到数据库中。
6.Collection是最基本的java集合接口,Set、List都继承了Collection,Map没有。
Set是最简单的一种集合,集合中的对象没有顺序,且不重复。Set接口主要实现了两个类,HashSet和TreeSet
List集合中的对象有顺序,且可以重复。接口实现了两个类,ArrayList和LinkedList
Map没有继承Collection接口,它存储的是键值对对象。
7.可以通过在HiberUtil中写
System.out.println(facyoty.openSession()==null);//下边这句也可以,这两段是等价的
System.out.println(HiberUtil.getSession()==null);
来生成数据库表,若为false,表示可以生成数据库。为true则不能生成表。而HiberUtil为
public class HiberUtil {
private static SessionFactory factory;
static{
Configuration conf = new AnnotationConfiguration().configure();//这里与原生的hibernate不同
factory = conf.buildSessionFactory();
}
public static Session getSession(){
return factory.openSession();
}
public static void main(String[] args) {
System.out.println(factory.openSession()==null);//通过该段代码生成表
//System.out.println(HiberUtil.getSession()==null);//这段代码也可以生成表
}
}
8.注解是一种配置,它和xml、properties文件作用类似,和注释不一样。
①注解是写到java代码中的键值对形式。
②String value是注解默认的书写方式
③target用来说明注解可以放在哪些地方,retention说明注解的生命周期,最长的是runtime
9.关于反射的invoke()方法
Class c = Test.class();//Test为一个java类
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("say");
m.invoke(obj);//表示执行obj的say方法,只是用了反射,相当于倒过来写
10.load和get方法,load有一个lazy属性,表示延迟加载。比get少了无效操作,比如查询数据库时,lazy会延迟加载,load会返回一个假的对象,即代理对象。
get方法没有懒加载问题,load方法有懒加载问题。
get先去session缓存中找,若没有就去数据库找,再没有就 返回null
load先去session缓存中找,若没有就去数据库找,再没有就 报异常
共同点就是都会先从一级缓存、二级缓存中去找,如果没有才去数据库找。
11.hibernate使用注解(annotation)步骤
①引入jar包,3个。ejb3-persistence,hibernate-annotations,hibernate-commons-annotations
②修改配置文件hibernate.cfg.xml,如原来的为
<mapping resource="com/bjsxt/po/User.hbm.xml" /> <!--注意结束标记,否则报错-->
则要修改为
<mapping class="com.bjsxt.po.User" />
其它不变
③原来的Configuration也得换
原来的
Configuration conf = new Configuration.configue();
factory = conf.buildSessionFactory();
修改为
Configuration conf = new AnnotationConfiguration().configure();//该处发生变化
factory = conf.buildSessionFactory();
12.
⑴在many-to-many关系中,那边可以设置mappedBy?
mappedBy作用是①放弃对外键的建立和维护②指定一个查询通道
如果不写mappedBy,那么就会产生多重复的中间表,只是表名不同,表中字段相同。
原则就是,哪边更新比较频繁,哪边就应该放弃外键的管理权。即写上mappedBy="某个值",如Student和Couse表,student更新比较频繁,则
/*********Student表***********/
@ManytoMany(mappedBy="students")
Set<Course> setCourse = new HashSet<Course>();
/*********Course表***********/
@ManytoMany
Set<Student> students = new HashSet<Student>();
⑵在one-to-many中,mappedBy的写法。
如在Grade和User中,一个班级对应多个用户
则mappBy放在one的一方(即在Grade中写@OneToMany(mappedBy="grade")),表示Grade放弃外键管理权
/*********Grade表***********/
@OneToMany(mappedBy="grade")
private Set<User> set = new HashSet<User>();
/*********User表***********/
@ManyToOne
private Grade grade;
⑶在one-to-one中,则有
如Company和Address为一对一,一个地址对应一个公司。mappedBy可置于任何一方,因为是一一对应。
除了用
@OneToOne(mappedBy="company")
这种写法外,还可以用
@ManyToOne
@JoinColumn(unique=true)
//这也可以用多对一,下边用unique表示多的一方也是唯一的,整体还是表示一对一
13.xml中,lazy属性默认都为true,即都为懒加载
注解中(annotation),则视情况而定。set集合为lazy(懒加载),单个元素为eager(不是懒加载)。懒加载归根结底还是为了节约资源。
14.hibernate中的注解释义:
@Entity表示当前为实体类
@Id 表示主键
@GeneratedValue 表示主键含义,默认表示自增,即主键为自增列
@Column 映射字段的含义,包括映射的数据库表的字段名称、是否允许为空、字段长度等。如:
@Column(name="id",unique=true,nullable=false,length=30)
//name:字段名称
//unique:是否唯一
//nullable:是否可以为空
//length:字段长度
这些字段除了name,都不是必须出现的。
15.hibernate.cfg.cml中的配置一定要写好结束符,否则会报错:
Could not parse configuration: /hibernate.cfg.xml.
如下边的两种结束方式都可以
<mapping class="com.bjsxt.po.Student"></mapping>
<mapping class="com.bjsxt.po.Course" />
而当出现这种错误是,可以先用浏览器打开该配置文件,浏览器会指出错误的位置。
16.在用注解生成数据库表时,除了在实体类前标注@Entity外,一定要在hibernate.cfg.xml中导入相应的mapping class,如:
<mapping class="com.bjsxt.po.Company" />
否则虽然不报错,但会生不成表。
17.在hibernate中,单个对象用uniqueResult()接收。集合一般用List接收。如
⑴单个对象
Session session = HiberUtil.getSession();
String hql = "select count(*) from Student";
Query query = session.createQuery(hql);
Number num = (Number) query.uniqueResult();//用Number类型接收,否则可能会由于long转int出错
int count = num.intValue();//再由Number转化为int
上述用Number类型接收,避免了可能由long转int出现的错
⑵集合
String hql = "slect new map(s.name as sname,s.tel as stel) from Student s";//注意hql写法,map为小写,list里存放的是map集合
//动态构造对象实例的方法,将数据封装.但这里的map封装的只是name和tel属性,不能进行更新操作
Query query = session.createQuery(hql);
List<Map<String,Object>> list = query.list();//虽然加入map,但还是由List接收整体
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Map<String, Object> map = (Map<String, Object>) iterator.next();
System.out.println(map.get("sname") + "********" + map.get("stel"));
}
还可以用数组接收
String hql = "select s.name,s.tel from Student s";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();//主要还是看这块的数组符号,list里存放的是Object数组
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object[] objects = (Object[]) iterator.next();//强制抓换也是用数组
System.out.println((String)obj[0] + "******" + (String)obj[1]);
}
或者用自定义的类接收,即可以加入VO层(写法和po中实体类差不多)
String hql = "select new com.bjsxt.vo.StudentVO(s.name,s.tel) from Student s";//注意hql写法,list里存放的是自定义类StudentVO,必须加包名。
//此时由于StudentVO要接收两个参数,所以在StudentVO中,除了get和set方法,无参构造器外,还必须有这两个参数的有参构造器。
Query query = session.createQuery(hql);
List<StudentVO> list = query.list();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
StudentVO stu = (StudentVO) iterator.next();
System.out.println(stu.getSname() + "********" + stu.getTel());
//getSname()和getTel()为StudentVO的方法
}
实际测试发现,这三种map和Object[],还有加入VO层的结果是一样的。虽然hql语句不同。
18.hql语句中可以利用Query接口和顺序占位符“?”进行参数填充,如
String hql = "from TUser user where user.name=? and user.age>?";
Query query = session.createQuery(hql);
query.setString(0,"Erica");
query.setInteger(1, 20);
也可以利用占位符填充参数
String hql = "from User where name=:name and pwd=:pwd";//注意该出的写法,前边有冒号
Query query = session.createQuery(hql);
query.setParameter("name","Erica");