JPA&Hibernate
JPA全称Java Persistence API.JPA,通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
Hibernate是之前很流行的ORM框架,也是JPA的一个实现,其它还有Toplink之类的ROM框架。
JPA和Hibernate之间的关系,可以简单的理解为JPA是标准接口,Hibernate是实现。
Hibernate主要是通过三个组件来实现的:
• hibernate-core:Hibernate的核心实现,提供了Hibernate所有的核心功能。
• hibernate-entitymanager:Hibernate实现了标准的JPA,可以把它看成hibernate-core和JPA 之间的适配器,它并不直接提供ORM的功能,而是对hibernate-core进行封装,使得Hibernate符合JPA的规范。
• hibernate-annotation:Hibernate支持annotation方式配置的基础,它包括了标准的JPA annotation以及Hibernate自身特殊功能的annotation。
1. @Entity
标识这个实体类是一个JPA实体,告诉JPA在程序运行的时候记得生成这个实体类所对应的表(需与@Id配合使用)
并且使用默认的 orm 规则,即 class 名即数据库表中表名,class 字段名即表中的字段名。 举例
@Entity
加上这两个注解之后,就可以作为一个实体类与数据库中的表相对应。他在数据库中的对应的表为:
2. @Id
声明主键
• @Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。
• @Id标注也可置于属性的getter方法之前。
3. @Table
是一个非必须的注解。指定了 Entity 所要映射的数据库表
其中 @Table.name() 用来指定映射表的表名。声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe),目录 (Catalog) 和 schema 的名字。如果同时使用了 @Entity(name=“student”) 和 @Table(name=“students”),最终的对应的表名必须是哪个?答案是 students,这说明优先级:@Table > @Entity。
4. @Column
描述数据库表中该字段的定义, 用来标识实体类中属性与数据表中字段的对应关系
具有以下属性:
• name:表示数据库表中该字段的名称,默认情形属性名称一致。
• nullable:表示该字段是否允许为null,默认为true。
• unique:表示该字段是否是唯一标识,默认为false。
• length:表示该字段的大小,仅对String类型的字段有效。
• insertable:表示在ORM框架执行插入操作时,该字段是否应出现INSETRT语句中,默认为true。
• updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true。对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段。
• columnDefinition:表示该字段在数据库中的实际类型。通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP。此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型,该属性非常有用。
补充:ORM框架:
对象-关系映射(Object-Relational Mapping,简称ORM),对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
5. @Transient
避免将该字段(属性)添加的数据库中(序列化到目的地)
1. 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2. transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3. 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
• 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
6. @GeneratedValue
规定主键生成策略
@GeneratedValue 用于标注主键的生成策略,通过strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer对应identity,MySQL 对应 auto increment。
举例:
@Table
或者:
@Table
7. @ManyToOne & @OneToMany
定义多对一和一对多关联表的属性
1. ManyToOne(多对一)单向:不产生中间表,但可以用@Joincolumn(name=" ")来指定生成外键的名字,外键在多的一方表中产生!
2. OneToMany(一对多)单向:会产生中间表,此时可以用@onetoMany @Joincolumn(name=" ")避免产生中间表,并且指定了外键的名字(别看@joincolumn在一中写着,但它存在在多的那个表中)
3. OneToMany ,ManyToOne 双向(两个注解一起用的):如果不在@OneToMany中加mappedy属性就会产生中间表,此时通常在@ManyToOne的注解下再添上注解@Joincolumn(name=" “)来指定外键的名字(说明:多的一方为关系维护端,关系维护端负责外键记录的更新,关系被维护端没有权利更新外键记录)!(@OneToMany(mappedBy=”一对多中,多中一的属性")出现mapby为被维护端(默认为延迟加载)
@ManyToOne():
@ManyToOne
• optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
• fetch:表示抓取策略,默认为FetchType.EAGER
• cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
• targetEntity:表示该属性关联的实体类型。该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity。
@OneToMany():
@OneToMany
• fetch = FetchType.Lazy 懒加载,作用是用到该属性的时候,才会将该属性加载到内存。加载employee对象时,并不会去立即加载dept属性。如果不设置,缺省为eager,急加载。
• cascade:表示级联操作策略
8. @JoinColumn
如果在entity class的field上定义了关系(@oneToOne或@oneToMany等),我们通过JoinColumn来定义关系的属性。JoinColumn的大部分属性和Column类似。
元数据属性说明:
• name:列名。
• referencedColumnName:该列指向列的列名(建表时该列作为外键列指向关系另一端的指定列)
• unique: 是否唯一
• nullable: 是否允许为空
• insertable: 是否允许插入
• updatable: 是否允许更新
• columnDefinition: 定义建表时创建此列的DDL
• secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。
9. @JsonIgnore
返回时忽略
后台返回时,不希望这个字段出现在json里(但是实体里想保留这个字段) 举例:
@JsonIgnore
10. @JsonProperty
请求时注入和序列化json属性名
1. 前端传参数过来的时候,使用这个注解,可以获取到前端与注解中同名的属性
2. 后端处理好结果后,返回给前端的属性名也不以实体类属性名为准,而以注解中的属性名为准
情况1举例:
@JsonProperty
情况2举例:
import
测试:
import
得到结果:
{"name":"张三"}
11. @RequestParam
从request中接收请求(参数)
看下面一段代码:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
根据上面的这个URL,你可以用这样的方式来进行获取
public
@RequestParam 支持下面四种参数
• defaultValue 如果本次请求没有携带这个参数,或者参数为空,那么就会启用默认值
• name 绑定本次参数的名称,要跟URL上面的一样
• required 这个参数是不是必须的
• value 跟name一样的作用,是name属性的一个别名
通俗的讲就是前段传给我一个json字典,getDetails()函数去接收,RequestParam()中的value相当于字典里的key,也就是用RequestParam()请求特定key的值,然后作为函数的实参传入。
12. @Autowired
它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作
被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据类型在ioc容器中找到匹配的类注入。
示例代码:
@Autowired
Car这个类被标注了,那么spring扫描到之后,发现需要Brand这个类的实例对象,那么spring会去ioc容器中找到类型匹配的对象注入。基本流程就是这样的,至于其他更复杂的问题,比如同一个类型的类有多个不同的bean,注入哪个,请百度吧。 当然,实现这种功能需要在ApplicationContext.xml中进行配置。
13. @Controller && @RestController
可以在控制器类中写各种业务方法,然后返回数据
一般数据的返回分成两大种,页面和 json 格式数据.现在一般应用都是前后分离,所以返回json数据的方式使用更频繁。我们有两种方式将返回的结果转化为josn: 使用 @Controller(修饰类) 和@ResponseBody(修饰方法) 两个注解,当然
• @ResponseBody还可以直接修饰类。 如果某个控制器类设计初衷就是返回json数据,那么该类可以使用简化方式
• @RestCotroller
@Target
从上面的源码中可以清晰的看到@RestController = @Controller + @ResponseBody
如何抉择
使用@Controller修饰类,可以根据需要返回各种我们所需的数据(json,ModelAndView,静态页面),而使用RestController修饰类,最后返回结果都会被解析成json字符串,适合所有方法返回值都是json数据
14. @GetMapping
用于处理HTTP GET请求,并将请求映射到具体的处理方法中。
具体来说,@GetMapping是一个组合注解,它相当于是@RequestMapping(method = RequestMethod.GET)的快捷方式。
15. @PostMapping
用于处理HTTP POST请求,并将请求映射到后端的处理方法中。
@PostMapping与@GetMapping一样,也是一个组合注解,它相当于是@RequestMapping(method=HttpMethod.POST)的快捷方式。
16. @DeleteMapping
用于处理HTTP DELETE请求,并将请求映射到删除方法中。
@DeleteMapping是一个组合注解,它相当于是@RequestMapping(method = HttpMethod.DELETE)的快捷方式。
17. @ResponseBody
会自动将控制器中方法的返回值写入到HTTP响应中。
特别的,@ResponseBody注解只能用在被@Controller注解标记的类中。如果在被@RestController标记的类中,则方法不需要使用@ResponseBody注解进行标注。@RestController相当于是@Controller和@ResponseBody的组合注解。
18. @PathVariable
将方法中的参数绑定到请求URI中的模板变量上。
可以通过@RequestMapping注解来指定URI的模板变量,然后使用@PathVariable注解将方法中的参数绑定到模板变量上。特别地,@PathVariable注解允许我们使用value或name属性来给参数取一个别名。下面是使用此注解的一个示例: 我们看下面的一个URL
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
上面的一个url你可以这样写:
@RequestMapping