必须提醒你:当应用程序继承现有的遗留数据库Schema时,通常应该尽可能地对现有的Schema少做一些改变。你
对Schema所做的每一处改变都可能破坏访问数据库的其他现有应用程序。现有数据的迁移可能很昂贵,这也是你要考虑
的问题。一般来说,构建一个新的应用程序不可能不对现有的数据模型做任何改变--新应用程序通常意味着
额外的业务需求,自然需要数据库Schema的演变。
处理主键:
不幸的是,遗留的数据库很多使用了自然主键、复合键,这样在业务需求改变时,很难重构数据库。
1、映射自然键
如你遇到的User表,可能userName是一个自燃键。那么你就需要告诉hibernate,标示符是在对象保存之前由应用
分配的一个自燃键:
JPA实现:
2、映射复合自然健
复合主键单独抽取出来一个实体来表示主键会比较优雅
代码:
UserID:要重装hashCode
User:
查询比较特别:
3、复合主键中的外键/4、复合主键的外键
代码:
配置文件:
插入:
5、利用注解的复合键
对Schema所做的每一处改变都可能破坏访问数据库的其他现有应用程序。现有数据的迁移可能很昂贵,这也是你要考虑
的问题。一般来说,构建一个新的应用程序不可能不对现有的数据模型做任何改变--新应用程序通常意味着
额外的业务需求,自然需要数据库Schema的演变。
处理主键:
不幸的是,遗留的数据库很多使用了自然主键、复合键,这样在业务需求改变时,很难重构数据库。
1、映射自然键
如你遇到的User表,可能userName是一个自燃键。那么你就需要告诉hibernate,标示符是在对象保存之前由应用
分配的一个自燃键:
- <class name="User" table="USER">
- <!-- PRIMARY KEY (`USER_NAME`) -->
- <id name="userName" column="USER_NAME">
- <generator class="assigned"></generator>
- </id>
- <property name="password"></property>
- </class>
JPA实现:
- @Entity
- public class User implements Serializable {
- @Id
- @Column(name="USER_NAME")
- private String userName;
- private String password;
2、映射复合自然健
复合主键单独抽取出来一个实体来表示主键会比较优雅
代码:
UserID:要重装hashCode
- public class UserId implements Serializable {
- private String userCode;
- private String userName;
- public UserId() {
- super();
- }
- public UserId(String userCode, String userName) {
- super();
- this.userCode = userCode;
- this.userName = userName;
- }
- public String getUserCode() {
- return userCode;
- }
- public void setUserCode(String userCode) {
- this.userCode = userCode;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result
- + ((userCode == null) ? 0 : userCode.hashCode());
- result = prime * result
- + ((userName == null) ? 0 : userName.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- UserId other = (UserId) obj;
- if (userCode == null) {
- if (other.userCode != null)
- return false;
- } else if (!userCode.equals(other.userCode))
- return false;
- if (userName == null) {
- if (other.userName != null)
- return false;
- } else if (!userName.equals(other.userName))
- return false;
- return true;
- }
- @Override
- public String toString() {
- return "UserId [userCode=" + userCode + ", userName=" + userName + "]";
- }
- }
User:
- public class User implements Serializable {
- private UserId userId;
- private String password;
查询比较特别:
- UserId userId = new UserId("code", "hello");
- User user = (User) session.get(User.class, userId);
3、复合主键中的外键/4、复合主键的外键
代码:
- public class User implements Serializable {
- private UserId userId;
- private String password;
- private Department department;
- private Set<Item> items = new HashSet<Item>();
- public class Department implements Serializable {
- private Integer departmentId;
- private String departmentName;
- private Set<User> users = new HashSet<User>();
- public class Item implements Serializable {
- private Integer itemId;
- private String itemName;
- private User user;
配置文件:
- <class name="User" table="USER">
- <composite-id name="userId" class="UserId">
- <key-property name="userCode" column="USER_CODE"></key-property>
- <key-property name="userName" column="USER_NAME"></key-property>
- </composite-id>
- <property name="password"></property>
- <many-to-one name="department" class="Department"
- column="DEPARTMENT_ID"
- cascade="save-update"></many-to-one>
- <set name="items" cascade="save-update" inverse="true">
- <key>
- <column name="USER_CODE"></column>
- <column name="USER_NAME"></column>
- </key>
- <one-to-many class="Item"/>
- </set>
- </class>
- <class name="Department" table="Department">
- <id name="departmentId" column="DEPARTMENT_ID">
- <generator class="native"></generator>
- </id>
- <property name="departmentName" column="department_Name"></property>
- <set name="users" inverse="true" cascade="save-update">
- <key column="DEPARTMENT_ID"></key>
- <one-to-many class="User"/>
- </set>
- </class>
- <class name="Item" table="Item">
- <id name="itemId" column="item_Id">
- <generator class="native"></generator>
- </id>
- <property name="itemName" column="item_Name"></property>
- <many-to-one name="user" class="User">
- <column name="USER_CODE"></column>
- <column name="USER_NAME"></column>
- </many-to-one>
- </class>
插入:
- User user = new User("123");
- UserId userId = new UserId("code", "hello");
- user.setUserId(userId);
- Department department = new Department("de hello");
- user.setDepartment(department);
- Item item = new Item("item1");
- user.getItems().add(item);
- //必须添加,因为,在<set name="items" cascade="save-update" inverse="true">设置了反向控制,
- //那么就由Item的user属性来控制之间的关系,所以Item的user必须知道user的存在
- //要知道这个东西和cascade="save-update"并不想干,cascade只是负责是否级联保存的,和表之间的关系由谁维护无关(这一点相信很多人都会搞混)
- item.setUser(user);
- session.save(user);
5、利用注解的复合键
- @Embeddable
- public class UserId implements Serializable {
- private String userCode;
- private String userName;
- @Entity
- public class User implements Serializable {
- @Id
- @AttributeOverrides({
- @AttributeOverride(name="userCode",
- column=@Column(name="user_Code")),
- @AttributeOverride(name="userName",
- column=@Column(name="user_Name"))
- })
- private UserId userId;
- private String password;
- @OneToMany(mappedBy="user")
- private Set<Item> items = new HashSet<Item>();
- @Entity
- public class Item implements Serializable {
- @Id
- @GeneratedValue
- @Column(name="ITEM_ID")
- private Integer itemId;
- private String itemName;
- // KEY `FK22EF338367E49C` (`user_Code`,`user_Name`),
- // CONSTRAINT `FK22EF338367E49C` FOREIGN KEY (`user_Code`, `user_Name`) REFERENCES `user` (`user_Code`, `user_Name`)
- @ManyToOne
- @JoinColumns({
- @JoinColumn(name="user_Code"),
- @JoinColumn(name="user_Name")
- })
- private User user;