必须提醒你:当应用程序继承现有的遗留数据库Schema时,通常应该尽可能地对现有的Schema少做一些改变。你
对Schema所做的每一处改变都可能破坏访问数据库的其他现有应用程序。现有数据的迁移可能很昂贵,这也是你要考虑
的问题。一般来说,构建一个新的应用程序不可能不对现有的数据模型做任何改变--新应用程序通常意味着
额外的业务需求,自然需要数据库Schema的演变。
处理主键:
不幸的是,遗留的数据库很多使用了自然主键、复合键,这样在业务需求改变时,很难重构数据库。
1、映射自然键
如你遇到的User表,可能userName是一个自燃键。那么你就需要告诉hibernate,标示符是在对象保存之前由应用
分配的一个自燃键:
JPA实现:
2、映射复合自然健
复合主键单独抽取出来一个实体来表示主键会比较优雅
代码:
UserID:要重装hashCode
User:
查询比较特别:
3、复合主键中的外键/4、复合主键的外键
代码:
配置文件:
插入:
5、利用注解的复合键
对Schema所做的每一处改变都可能破坏访问数据库的其他现有应用程序。现有数据的迁移可能很昂贵,这也是你要考虑
的问题。一般来说,构建一个新的应用程序不可能不对现有的数据模型做任何改变--新应用程序通常意味着
额外的业务需求,自然需要数据库Schema的演变。
处理主键:
不幸的是,遗留的数据库很多使用了自然主键、复合键,这样在业务需求改变时,很难重构数据库。
1、映射自然键
如你遇到的User表,可能userName是一个自燃键。那么你就需要告诉hibernate,标示符是在对象保存之前由应用
分配的一个自燃键:
- <classname="User"table="USER">
- <!-- PRIMARY KEY(`USER_NAME`) -->
- <id name="userName"column="USER_NAME">
- <generatorclass="assigned"></generator>
- </id>
- <property name="password"></property>
- </class>
JPA实现:
- @Entity
- publicclassUserimplementsSerializable {
- @Id
- @Column(name="USER_NAME")
- privateString userName;
- privateString password;
2、映射复合自然健
复合主键单独抽取出来一个实体来表示主键会比较优雅
代码:
UserID:要重装hashCode
- publicclassUserIdimplementsSerializable {
- privateString userCode;
- privateString userName;
- publicUserId() {
- super();
- }
- publicUserId(String userCode, String userName) {
- super();
- this.userCode = userCode;
- this.userName = userName;
- }
- publicString getUserCode() {
- returnuserCode;
- }
- publicvoidsetUserCode(String userCode) {
- this.userCode = userCode;
- }
- publicString getUserName() {
- returnuserName;
- }
- publicvoidsetUserName(String userName) {
- this.userName = userName;
- }
- @Override
- publicinthashCode() {
- finalintprime =31;
- intresult =1;
- result = prime * result
- + ((userCode ==null) ?0: userCode.hashCode());
- result = prime * result
- + ((userName ==null) ?0: userName.hashCode());
- returnresult;
- }
- @Override
- publicbooleanequals(Object obj) {
- if(this== obj)
- returntrue;
- if(obj ==null)
- returnfalse;
- if(getClass() != obj.getClass())
- returnfalse;
- UserId other = (UserId) obj;
- if(userCode ==null) {
- if(other.userCode !=null)
- returnfalse;
- }elseif(!userCode.equals(other.userCode))
- returnfalse;
- if(userName ==null) {
- if(other.userName !=null)
- returnfalse;
- }elseif(!userName.equals(other.userName))
- returnfalse;
- returntrue;
- }
- @Override
- publicString toString() {
- return"UserId [userCode="+ userCode +", userName="+ userName +"]";
- }
- }
User:
- publicclassUserimplementsSerializable {
- privateUserId userId;
- privateString password;
查询比较特别:
- UserId userId =newUserId("code","hello");
- User user = (User) session.get(User.class, userId);
3、复合主键中的外键/4、复合主键的外键
代码:
- publicclassUserimplementsSerializable {
- privateUserId userId;
- privateString password;
- privateDepartment department;
- privateSet<Item> items =newHashSet<Item>();
- publicclassDepartmentimplementsSerializable {
- privateInteger departmentId;
- privateString departmentName;
- privateSet<User> users =newHashSet<User>();
- publicclassItemimplementsSerializable {
- privateInteger itemId;
- privateString itemName;
- privateUser user;
配置文件:
- <classname="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-manyclass="Item"/>
- </set>
- </class>
- <classname="Department"table="Department">
- <id name="departmentId"column="DEPARTMENT_ID">
- <generatorclass="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-manyclass="User"/>
- </set>
- </class>
- <classname="Item"table="Item">
- <id name="itemId"column="item_Id">
- <generatorclass="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 =newUser("123");
- UserId userId =newUserId("code","hello");
- user.setUserId(userId);
- Department department =newDepartment("de hello");
- user.setDepartment(department);
- Item item =newItem("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
- publicclassUserIdimplementsSerializable {
- privateString userCode;
- privateString userName;
- @Entity
- publicclassUserimplementsSerializable {
- @Id
- @AttributeOverrides({
- @AttributeOverride(name="userCode",
- column=@Column(name="user_Code")),
- @AttributeOverride(name="userName",
- column=@Column(name="user_Name"))
- })
- privateUserId userId;
- privateString password;
- @OneToMany(mappedBy="user")
- privateSet<Item> items =newHashSet<Item>();
- @Entity
- publicclassItemimplementsSerializable {
- @Id
- @GeneratedValue
- @Column(name="ITEM_ID")
- privateInteger itemId;
- privateString 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")
- })
- privateUser user;