Hibernate Notes:
<1>.总结学习: [hibernate 关联关系]
1.<单向多对一关联>
注:以City类和teams类为例:
1)配置文件,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 配置SQL是否在控制台进行打印 -->
<property name="show_sql">true</property> <!-- 配置SQL是否在输出的时候进行格式化 -->
<property name="format_sql">true</property>
<!-- 配置连接数据库的信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">123456</property>
<!-- 配置生成数据表的方式 -->
<property name="hbm2ddl.auto">update</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 配置映射关系文件的加载路径 -->
<mapping resource="qau/edu/summarize/City.hbm.xml" /> <mapping resource="qau/edu/summarize/Teams.hbm.xml" /> </session-factory> </hibernate-configuration>
|
反思和总结:
1. 当编写上面的配置文件的时候,自己经常忘记的就是没有配置实体类映射的数据表在数据库中的生成方式,<property name=”hbm2ddl.auto”>update</property>.
2. 配置SQL的控制台的格式也是一种标准和规范,show_sql:配置是否在控制台进行SQL的打印;format_sql:配置是否在输出SQL时进行格式化。
3. 还要注意的就是配置加载关系映射文件的路径的时候格式是“/”;
4. 为了在初学编写代码的时候忘记一些步骤(就像现在的自己),要在编写之前把步骤以注释的形式罗列出来,然后好像填空一样进行代码的完善,不但能使自己的编写思路清晰,还能提高代码的可读性。要养成这样的习惯。
2)编写POJO,代码如下:
package qau.edu.summarize;
public class City {
private int id ; private String name ; private int number ; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; }
public int getId() { return id; } public void setId(int id) { this.id = id; }
public City(String name, int number) { super();
this.name = name; this.number = number; } public City() { super(); } @Override public String toString() { return "City [id=" + id + ", name=" + name + ", number=" + number + "]"; }
}
|
package qau.edu.summarize;
public class Teams {
private int id ; private String name ; private int score ;
private City city ;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getScore() { return score; }
public void setScore(int score) { this.score = score; }
public City getCity() { return city; }
public void setCity(City city) { this.city = city; }
public Teams(String name, int score, City city) { super(); this.name = name; this.score = score; this.city = city; }
public Teams() { super(); }
@Override public String toString() { return "Teams : [id=" + id + ", name=" + name + ", score=" + score + ", city=" + city + "]"; }
}
|
反思和总结:
- 1. 编写POJO,要理解什么是POJO?
POJO:(plain old Java Object)所以,他是传统简单的Java类,满足POJO的条件就是:
1)属性私有;(必须)
2)提供一个标识符属性,使其作为数据库中的主键;(OID必须)
3)每个属性都带有自己的setter和getter方法;(设值)
4)提供一个默认的无参构造方法;(必须)
5)实现serializible接口;(非必须)
6)POJO是非final类;
- 2. 为了测试方便可以在POJO中编写相应的toString()方法,还有就是里面的带有参数的构造方法是为了实例化方便,也就是说,在实例化时候可以直接初始化,不需要再进行set属性,不是必须的。
3)编写关系映射文件,代码如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="qau.edu.summarize">à把全类名提出来,方便下面的书写;
<class name="City" table="t_city">----------POJO的类(City类名)映射成数据库中表(t_city自定义数据 库表名)
<id name="id" type="int"> POJO属性映射成数 据表中的字段(列) <column name="c_id" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="c_name" /> </property>
<property name="number" type="int"> <column name="c_number" /> </property>
</class>
</hibernate-mapping>
|
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="qau.edu.summarize">
<class name="Teams" table="t_teams">
<id name="id" type="int"> <column name="t_id" /> <generator class="native" /> </id>
<property name="name" type="java.lang.String"> <column name="t_name" /> </property>
<property name="score" type="int"> <column name="t_score" /> </property>
<!-- 配置多对一的单向关联关系 -->
<many-to-one name="city" class="City" column="t_city"/> 关键
</class> </hibernate-mapping>
|
总结:
1) 通过映射文件就可以很好的理解“ORM”:对象/关系映射,本质就是POJO的一个实例化对 象,映射成在数据库中相应的数据表,用于永久的存放数据(持久化),POJO中的属性映射成数据表的相应的字段(列),其中,用于标记的属性,是数据表中的主键。
2) <many-to-one name="city" class="City" column="t_city"/>这是单向多对一的关键。对于单向多对一关联关系,谁访问谁,就在主动方中添加该属性,(主动访问的一方叫做主动方),用于设置多对一的关联关系,并且维护这种关联关系。
其中,name对应“待持久化对象的在当前实体类中的对应的属性变量名”,class对应着待持久化对象的实体类名,column对应着生成的主键在数据表中的列。
4)编写测试类,代码实现如下:
package qau.edu.summarize;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration;
public class Test {
public static void main(String[] args) {
// 创建configuration对象,加载配置文件并且进行解析; 加载配置文件,用于解析配置文件, Configuration con = new Configuration().configure();-- 开启整个hibernate框架。 创建SessionFactory (Session工厂),用 // 创建SessionFactory; 创建Session;
SessionFactory factory = con.buildSessionFactory();
// 创建Session;
Session session = factory.openSession();
// 打开一个事务;
Transaction tr = session.beginTransaction(); 开始一个事务,用于增删改查操作;
// 实例化对象;
City city = new City("Qingdao", 98989);
Teams team = new Teams(); team.setId(1); team.setName("Lakers"); team.setCity(city);
Teams team2 = new Teams(); team2.setId(2); team2.setName("hart"); team2.setCity(city);
// 保存对象; session.save(city); session.save(team); session.save(team2);
// 提交事务;
tr.commit();
// 关闭Session;
session.close(); } } |
执行代码:
Hibernate: insert into t_city (c_name, c_number, c_date) values (?, ?, ?) Hibernate: insert into t_temas (t_name, t_color, t_date, c_id) values (?, ?, ?, ?) Hibernate: insert into t_temas (t_name, t_color, t_date, c_id) values (?, ?, ?, ?)
|
总结:
上面的执行结果只是有三个insert,说明进行插入了三条记录,这是正确的和符合我们要求的;但是这样的运行结果和save操作的顺序是有关系的。
1)第一种情况就是上面的结果,也就是先插入city对象,再插入teams对象;
2)第二种情况就是:先插入teams对象,再插入City对象,但是结果却是不同的;看代码:
Hibernate: insert into t_temas (t_name, t_color, t_date, c_id) values (?, ?, ?, ?) Hibernate: insert into t_temas (t_name, t_color, t_date, c_id) values (?, ?, ?, ?) Hibernate: insert into t_city (c_name, c_number, c_date) values (?, ?, ?) Hibernate: update t_temas set t_name=?, t_color=?, t_date=?, c_id=? where t_id=? Hibernate: update t_temas set t_name=?, t_color=?, t_date=?, c_id=? where t_id=? |
通过运行结果可以看到:不但是进行了三条insert操作,并进行了两条update操作,为什么呢?
因为在先插入teams的一端(即先插入n的一端)时候,对应的外键值是不知道的,因为City(也就是一的一端)根本没有进行插入,当第一次进行City(一的一端)时候,感知到有了一个外键值,就会进行一次update操作,用以进行外键的插入,以此类推,就会进行两次update的操作。
总结:
在进行save操作,即进行插入操作的时候,在决定插入对象的顺序时,应该先插入一的“一”端,然后再进行“多”的一端的插入,因为验证已经知道,如果先插入“多”的一端会多出两条update语句,也就会降低了效率。
自己出现的错误:
今天进行复习,编写代码的时候,出现了一个以前没有出现的错误。
昨天晚进行代码编译时,到了最后进行运行测试的时候,竟然出现一个没有遇到过的错误,就行提示“invalid conguration”就是一个无效的配置文件,自己进行检查时,没有发现,然后就去网上求助,尝试了很多,就是没有解决。然后排除代码问题,查找配置,觉得头文件有问题,就进行了remove,然后重新加载,竟然好了,其实,我是在网上试过,复制,然后粘贴进来,但是就是无效,最后我是这样解决的:
在eclipse中配置:
步骤:
Window-----preferences------XML------XMLCatalog----User Specified Entres
在User Specified Entres这里有的文件hibernate-configuration-dtd之类的进行remove,然后重新加载
点击“Add”------”Key type”选择URL----然后点击”File System”---就会提示你找你自己下载好的hibernate-release-4.2.4.Final文件包---hibernate-release-4.2.4.Finalprojecthibernate-coresrcmain esourcesorghibernate知道找到hibernate-configuration-3.0.dtd文件,直接打开就行了,这样当你在利用hibernate插件进行hibernate-cfg-xml配置文件的时,就不会出现头文件出错了。(出错即收获)