之前的映射文件配置都是简单的、基础的配置,只涉及到单个javabean,对于单个javabean的增删改查都能很好的、简单的去完成。
但是知道简单配置远远不够,并不能完成很多复杂的情况,比如对象与对象间的关联,对象中的集合属性等,所以还需更近一步的学习hibernate映射文件的配置。
本次映射文件配置涉及到集合、排序、多对一、一对多、多对多、以及一对一的内容等。
1.集合属性(Set、List、Map、数组)
1.1Set集合:
首先,创建一个User实体类,实体类是一个买家账号,包含id、name、addressSet(set集合,存放多个地址,地址不重复)
//该实体是买家实体 public class User { private Integer id;// 买家id private String name;// 买家名字 private Set<String> addressSet;// 买家地址,可以有多个,但是不能重复 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<String> getAddressSet() { return addressSet; } public void setAddressSet(Set<String> addressSet) { this.addressSet = addressSet; } }
接着配置映射文件
<?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="com.hibernate.Collection"> <class name="User" table="user"> <id name="id" type="int" column="id"> <generator class="native"/> </id> <property name="name" type="string" column="name" length="20"/> <!-- addressSet属性,在javabean中是一个set集合 --> <!-- name为javabean中的属性名,table为另一张表user_addr --> <!-- user_addr表主键其实是user表的外键 --> <set name="addressSet" table="user_addr"> <!-- user_addr外键 --> <key column="addrId"/> <!-- user_addr表address列 --> <element type="string" column="address"/> </set> </class> </hibernate-mapping>
表结构如下:
CREATE TABLE `user` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) NULL DEFAULT NULL, PRIMARY KEY (`id`) ) COLLATE=‘utf8_general_ci‘ ENGINE=InnoDB AUTO_INCREMENT=2; CREATE TABLE `user_addr` ( `addrId` INT(11) NOT NULL, `address` VARCHAR(255) NULL DEFAULT NULL, INDEX `FK14340FE5D5E4BA1E` (`addrId`), CONSTRAINT `FK14340FE5D5E4BA1E` FOREIGN KEY (`addrId`) REFERENCES `user` (`id`) ) COLLATE=‘utf8_general_ci‘ ENGINE=InnoDB;
测试程序:
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static void main(String[] args) { User u = new User(); u.setId(1); u.setName("testName"); Set<String> s = new HashSet<String>(); s.add("BeiJing 12"); s.add("HongKong 35"); s.add("ShangHai 113"); u.setAddressSet(s); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx= session.beginTransaction(); tx.begin(); session.save(u); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally{ session.close(); sessionFactory.close(); } } }
最终hibernate帮我们执行的sql代码:
Hibernate: insert into user (name) values (?) Hibernate: insert into user_addr (addrId, address) values (?, ?) Hibernate: insert into user_addr (addrId, address) values (?, ?) Hibernate: insert into user_addr (addrId, address) values (?, ?)
上述程序说明:
实体类User是一个买家账号类,该账号的id和name配置不多描述,主要说明addressSet集合,该集合存放多个地址,那么当我们存储数据到数据库中,user表的数据应该是这样子的:
id name 1 testName 2 testName2
由于一个User地址是多个,所以地址没办法在user表中的一个账号中体现出来,唯有创建一张地址表,用来被user表的用户指向,那么地址表的数据就是这样子的:
addrId address 1 123号 1 456号 2 789号
所以我们再次查看配置文件有关于集合的配置:
<set name="addressSet" table="user_addr"> <!-- user_addr外键 --> <key column="addrId"/> <!-- user_addr表address列 --> <element type="string" column="address"/> </set>
上述配置,set name代表的是javabean中的集合名称,而table代表的是地址表user_addr,同时必须指出地址表的外键,以及地址表其他字段。
举一反三,知道怎么存入数据,当然要知道怎么获取数据:
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static void main(String[] args) { User u = new User(); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx= session.beginTransaction(); tx.begin(); u = (User) session.get(User.class, 1); System.out.println(u); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally{ session.close(); sessionFactory.close(); } } }
hibernate帮我们查询的sql代码:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from user user0_ where user0_.id=? Hibernate: select addressset0_.addrId as addrId0_0_, addressset0_.address as address0_ from user_addr addressset0_ where addressset0_.addrId=?
得出结果:
User [id=1, name=testName, addressSet=[BeiJing 12, ShangHai 113, HongKong 35]]
1.2List集合,跟set集合很相似,唯一的不同是在映射文件的集合配置
把实体类属性更改一下:
//该实体是买家实体 public class User { private Integer id;// 买家id private String name;// 买家名字 private List<String> cargo;// 购物车商品,可多个,也可重复 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getCargo() { return cargo; } public void setCargo(List<String> cargo) { this.cargo = cargo; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", cargo=" + cargo + "]"; } }
映射文件配置,相比set集合配置多了一个<list-index>标签:
<?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="com.hibernate.Collection"> <class name="User" table="user"> <id name="id" type="int" column="id"> <generator class="native"/> </id> <property name="name" type="string" column="name" length="20"/> <list name="cargo" table="cargo_list"> <key column="cargoId"/> <!-- list集合表,同一个用户购物车商品的顺序 --> <list-index column="idx"/> <element type="string" column="cargoName"/> </list> </class> </hibernate-mapping>
测试程序:
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static void main(String[] args) { User u = new User(); u.setId(1); u.setName("testName"); List<String> cargoList = new ArrayList<String>(); cargoList.add("pancel"); cargoList.add("apple"); cargoList.add("water"); u.setCargo(cargoList); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx= session.beginTransaction(); tx.begin(); session.save(u); System.out.println(u); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally{ session.close(); sessionFactory.close(); } } }
查看hibernate帮我们生成的sql语句:
Hibernate: insert into user (name) values (?) User [id=1, name=testName, cargo=[pancel, apple, water]] Hibernate: insert into cargo_list (cargoId, idx, cargoName) values (?, ?, ?) Hibernate: insert into cargo_list (cargoId, idx, cargoName) values (?, ?, ?) Hibernate: insert into cargo_list (cargoId, idx, cargoName) values (?, ?, ?)
表结构和数据:
user表
cargo_list表
1.3数组(跟list集合配置一模一样,除了list集合标签使用<list></list>,而数组使用<array></array>)
依旧是更改一下user实体
//该实体是买家实体 public class User { private Integer id;// 买家id private String name;// 买家名字 private String[] cargo;// 购物车商品,可多个,也可重复 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String[] getCargo() { return cargo; } public void setCargo(String[] cargo) { this.cargo = cargo; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", cargo=" + cargo + "]"; } }
映射文件配置:
<?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="com.hibernate.Collection"> <class name="User" table="user"> <id name="id" type="int" column="id"> <generator class="native"/> </id> <property name="name" type="string" column="name" length="20"/> <array name="cargo" table="user_addressArray"> <key column="addrId"/> <list-index column="idx"/> <element type="string" column="address"/> </array> </class> </hibernate-mapping>
测试程序:
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static void main(String[] args) { User u = new User(); u.setId(1); u.setName("testName"); String[] cargo = {"computer","iphone6s","ipad"}; u.setCargo(cargo); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx= session.beginTransaction(); tx.begin(); session.save(u); System.out.println(u); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally{ session.close(); sessionFactory.close(); } } }
查看hibernate为我们生成的sql语句:
Hibernate: insert into user (name) values (?) User [id=1, name=testName, cargo=[Ljava.lang.String;@f737a7] Hibernate: insert into user_addressArray (addrId, idx, address) values (?, ?, ?) Hibernate: insert into user_addressArray (addrId, idx, address) values (?, ?, ?) Hibernate: insert into user_addressArray (addrId, idx, address) values (?, ?, ?)
表结构和数据:
user表
user_addressArray表
1.4Map集合
仍然修改一下user实体
//该实体是买家实体 public class User { private Integer id;// 买家id private String name;// 买家名字 private Map<String,String> map = new HashMap<String,String>();// 地址+邮政编码 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", map=" + map + "]"; } }
映射文件配置:
<?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="com.hibernate.Collection"> <class name="User" table="user"> <id name="id" type="int" column="id"> <generator class="native"/> </id> <property name="name" type="string" column="name" length="20"/> <map name="map" table="user_map"> <!-- user_map外键 --> <key column="mapId"/> <!-- 由于javabean属性是map集合,所以必须配置key和value --> <map-key type="string" column="mapKey"/> <element type="string" column="mapValue"/> </map> </class> </hibernate-mapping>
测试程序:
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static void main(String[] args) { User u = new User(); u.setId(1); u.setName("testName"); Map<String,String> map = new HashMap<String,String>(); map.put("xiaMen", "361100"); map.put("fuZhou", "351100"); u.setMap(map); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx= session.beginTransaction(); tx.begin(); session.save(u); System.out.println(u); tx.commit(); } catch (HibernateException e) { tx.rollback(); e.printStackTrace(); } finally{ session.close(); sessionFactory.close(); } } }
hibernate帮我们生成的sql语句:
Hibernate: insert into user (name) values (?) User [id=2, name=testName, map={xiaMen=361100, fuZhou=351100}] Hibernate: insert into user_map (mapId, mapKey, mapValue) values (?, ?, ?) Hibernate: insert into user_map (mapId, mapKey, mapValue) values (?, ?, ?)
表结构和数据:
user表
user_map表
2.排序order-by
说明,这里的orderby指的是查询出来的集合表中数据的排序,只能在映射文件的集合中配置
<!-- orderby排序的是集合表的数据, 由于集合表现在有3个字段(从以下很容易看出mapId、mapKey、mapValue), 所以通过哪个字段排序看你自己 ; order-by内可以指定排序:ASC DESC,默认是ASC,不区分大小写 --> <map name="map" table="user_map" order-by="mapKey DESC"> <!-- user_map外键 --> <key column="mapId"/> <!-- 由于javabean属性是map集合,所以必须配置key和value --> <map-key type="string" column="mapKey"/> <element type="string" column="mapValue"/> </map>
3.多对一和一对多以及一对一和多对多
未完待续。。。