十四滴水:Hibernate(五)之Hibernate属性级别注解
上一篇文章学习了类级别的注解这一篇我们学习的是属性级别注解:
Hibernate添加属性级别注解的方式有两种:
1.写在属性字段上面
2.写在属性的get访问器的上面
上图中的是hibernate中常用的属性级别注解 红色的是我们这篇文章准备学习的注解
aaa@qq.com注解
id注解在我们的实体类当中是必须的,定义了映射到数据库表当中的主键的属性,一个实体类可以有一个或多个属性被映射成为主键,可置于主键属性或者getXXX之前。
需要注意的是 ,如果一个实体类当中有多个属性被定义为主键属性,那么这个实体类就必须要 实现serializable接口。
下面我们用代码具体实现一下:
我们把之前的get方法之前的@id注释掉,直接放在声明属性之前:
@Id
private int sid;//学号
@Id
@Column(length=8)
private String sname;//学生的姓名
在这里我发现了一个问题:之前我们没有注释掉在get方法之前的id注释 同时在前面的属性声明前面去给另外的属性去添加id注释 结果并没有成功 仍然是只有被注释的那个get属性的主键生效了 这是因为get的优先级大于属性的优先级。
此外String类型如果不声明长度的话,数据库中并不会生成主键,这是因为MySQL的设置主键的要求是长度不能超过255,所以我们这个时候就用到了column标签,指定一下sname的长度,就可以成功的设置了:
aaa@qq.com注解
@GeneratedValue(strategy=“”,generator=“”)
strategy是策略属性,它是我们JPA注解所定义的一些主键生成策略,generator是主键生成器属性(这两个都是用来指定我们主键的生成策略的 )。
常见的主键生成策略有四种:
1.GenerationType.AUTO类型:根据底层数据库来自动选择,同时它也是我们的默认值,意思就是如果我们的value不设置任何值的话,它默认的就是AUTO类型。
2.GenerationType.IDENTITY:它是一种标识列,也就是它必须是唯一的。根据数据库的Identity字段生成;
3..GenerationType.SEQUENCE(序列):使用sequence来决定主键的取值。
4.GenerationType.Table:使用指定表来决定主键的取值,要结合@TableGenerator一起使用
我们去实践证明一下:
@Id
@GeneratedValue
private int sid;//学号
我们把学号前面加上GeneratedValue属性标签运行结果:
因为sid是int类型 所以GeneratedValue它默认的主键类型就是自动增长类型;
aaa@qq.com注解
column属性顾名思义就是把我们实体类中的属性映射到表当中之后 对应的就是表当中的字段,@column注解详细的描述了数据库表中该字段的详细的定义,column注解常用的属性如下:
aaa@qq.com注解
Embedded注解是用来注释属性的,表示该属性的类是嵌入类。
需要注意的是,同时嵌入类也必须标注@Embeddble注解。
aaa@qq.com注解
EmbeddedId注解是使用嵌入式主键类实现符合主键,嵌入式主键类必须要实现serializable接口,同时也必须要有public的无参构造方法,同时还必须重写从object继承而来的equals和hashcode方法。
接下来我们来实际的去操作一下:
package com.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
//学生主键类
@Embeddable
public class StudentsPK implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Column(length=18)
private String id;
@Column(length=8)
private int sid;
public StudentsPK(){
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
@Override
public boolean equals(Object arg0) {
// TODO Auto-generated method stub
return super.equals(arg0);
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
}
package com.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;/*JPA注解*/
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
//学生实体类 有了这个注解就可以保证我们的实体类将来会映射成数据库当中的一张表
//@Entity(name="t_students")
@Entity
@Table(name="t_students",schema="hibernate_zhangxin")
public class Students implements Serializable {
// @Id
// @GeneratedValue
@EmbeddedId
private StudentsPK pk;//学号
// @Id
// @Column(length=8)
private String sname;//学生的姓名
private String gender;//学生的性别
private Date birthday;//学生的生日
private String major;//学生的专业
//private String address;//地址
private Address add;//地址
public Students(){
}
public Students(StudentsPK pk, String sname, String gender, Date birthday,
String major,Address add) {
//super();
this.pk = pk;
this.sname = sname;
this.gender = gender;
this.birthday = birthday;
this.major = major;
//this.address = address;
this.add=add;
}
// public int getSid() {
// return sid;
// }
// public void setSid(int sid) {
// this.sid = sid;
// }
public String getSname() {
return sname;
}
public StudentsPK getPk() {
return pk;
}
public void setPk(StudentsPK pk) {
this.pk = pk;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
// public String getAddress() {
// return address;
// }
// public void setAddress(String address) {
// this.address = address;
// }
public Address getAdd() {
return add;
}
public void setAdd(Address add) {
this.add = add;
}
}
得到的结果:
联合主键。
我们来尝试一下添加信息:
@Test
public void addStudents(){
//创建hibernate配置对象
Configuration config=new Configuration().configure();
//创建服务注册对象
ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
//生成sessionFactory
SessionFactory sessionFactory=config.buildSessionFactory(serviceRegistry);
//创建会话
Session session=sessionFactory.getCurrentSession();
//创建事务
Transaction tx=session.beginTransaction();
//创建一个学生对象
Address add=new Address();
add.setAddress("深圳");
add.setPhone("8208208820");
add.setPostCode("55555");
//学生主键
StudentsPK pk=new StudentsPK();
pk.setId("123456789012345678");
pk.setSid(123);
Students s =new Students(pk,"迟人华","男",new Date(),"啦啦啦",add);
session.save(s);
tx.commit();
}
中间出现了一个bug是我忘记配置cfg.xml了:
org.hibernate.HibernateException: No CurrentSessionContext configured!
解决办法:https://blog.csdn.net/zhang1su2juan3/article/details/5387900
最后运行出来的结果:
6.Transient注解
可选注解,表示该属性并非要映射到数据库表当中的某一个字段,ORM框架在解析这个注解的时候,会把这个属性给忽略掉,这个属性将不会被映射到我们数据库表当中的某一个字段,如果我们不加上这个@Transient,那么这个属性就将会被映射成某一个字段。注意如果一个属性并非是数据库表的字段映射,那么就务必要把它标示为@Transient,否则ORM会将其默认标注为@Basic。
下面我们来实验一下:
我们添加一个新的属性,叫做工资,工资一般情况下都是私密的,所以我们并不想让这个属性出现在数据库的字段当中;
首先我们先添加一个salary属性到数据库当中:
在实体类中添加并进行封装:
private double salary;//薪水
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
删除数据库中原有的表,运行测试类:
会发现出现了一条叫做salary的属性,接下来我们在实体类中salary属性之前添加注释:
@Transient//表示该属性不会被映射到ORM表里的字段
private double salary;//薪水
我们再运行一次测试类:
这时候我们发现salary不见了,我们再看一下数据库中的数据:
salary没有出现。
PS:嗯 这篇博客 我拖了一个一个星期才整完哈哈哈哈罪恶了:)
下一篇: MAYA7.0制作人体皮肤材质的英文教程