JPA学习笔记

JPA学习笔记

JPA是一种规范,而Hibernate,EclipseLink,OpenJPA都是它的一种实现。Spring Data JPA 是简化JPA的写法的实现,封装常用的写法。

一、基本知识

1. JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的

<!-- src/main/resources/META-INF/persistence.xml -->
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"  
        version="1.0">  
        <persistence-unit name="testdb" transaction-type="RESOURCE_LOCAL">  
        	<provider>org.hibernate.ejb.HibernatePersistence</provider>
		    <class>com.domain.entity.User</class>
            <class>com.domain.entity.Role</class>
            <properties>
            <!--  
            <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver" />  
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />  
            <property name="hibernate.connection.username" value="root" />  
            <property name="hibernate.connection.password" value="123456" />  
            -->
 			<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory" />
			<property name="net.sf.ehcache.configurationResourceName" value="/ehcache.xml" />
			<property name="hibernate.cache.use_second_level_cache" value="true" />
			<property name="hibernate.cache.use_structured_entries" value="true" />
			<property name="hibernate.cache.use_query_cache" value="true" />
			<property name="hibernate.hbm2ddl.auto" value="update" />
			<property name="hibernate.generate_statistics" value="false" />
			<property name="hibernate.jdbc.fetch_size" value="64" />
			<property name="hibernate.jdbc.batch_size" value="32" />
            <!--<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />  -->
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
			<property name="hibernate.format_sql" value="false" />
             <property name="hibernate.show_sql" value="true" />  
             <!-- <property name="hibernate.max_fetch_depth" value="1" /> -->
			<property name="javax.persistence.validation.group.pre-persist" value="javax.validation.groups.Default" />
			<property name="javax.persistence.validation.group.pre-update" value="javax.validation.groups.Default" />                
            </properties>  
        </persistence-unit>  
    </persistence>  

2. JPA ORM映射元素数据有XML和注解两种方式

1)在实体bean中用注解@Entity来指定实体以让jpa知道生成数据库中的表
2)在实体bean中用注解@Column(length,nullable,name)指定数据库中的表的字段的长度,是否为空即字段的名字
3)在实体类的前面用注解@Table(name="xx")指定生成表的名字
4)在实体类中用注解@Temporal(TemporalType.Date)指定生日的时间类型
5) @Enumerated(EmumType.STRING//保存到数据库中是索引还是字符串)注解指定枚举类型
6) @Lob声明属性对应的数据库字段为大文本类型,可以存放大的数据(文本和字节)
7) @Transient不成为持久化字段及不跟数据库中的字段形成映射
8) @Basic(fetch=FetchType.LAZY)//是否把数据装载到内存中延迟初始化,第一次访问的时候在加载数据,一般用在大数据存放
9) @Embeddable指定联合组键
一个实体类要在多个不同的实体类中进行使用,而本身又不需要独立生成一个数据库表,就需要使用@Embedded、@Embeddable

@MappedSuperclass
public class IDEntity implements java.io.Serializable{
	@Id
    @GeneratedValue
    private Integer id;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="create_date", updatable=false)
	public Date createDate;	
}

@Entity
@Table(name="city")
public class City extends IDEntity{}

@Entity
@Table(name="brand",uniqueConstraints = { @UniqueConstraint(columnNames = {"mobile_brand", "mobile_model"})})
public class Brand extends  IDEntity {
	@Column(name = "mobile_brand")
	public String brand;
	
	@Column(name = "mobile_model")
	public String model;

    @ManyToOne
    @NotFound(action=NotFoundAction.IGNORE)
    private City city;

    @Column(name="frequency",columnDefinition="INT(11) DEFAULT 0  NULL  COMMENT '请求频率'")
    private int frequency;

    @Transient
    private ChannelParameter channelParameter;

    @OneToOne(mappedBy = "channel",fetch = FetchType.LAZY)
    private ChannelParameter channelParameter;

    @Lob  
    @Basic(fetch = FetchType.LAZY)  
    @Column(columnDefinition = "TEXT",name = "content")
    private String content;
}

3. JPA的增删改查:

1)读取数据不要开启事务,只要有更改数据的动作才需要开启事务
2)增加数据:em.persist(new Person("Jack"));//插入
3)删除数据:em.remove(person); //删除(注意有外键约束时,需要先解除外键约束才能删除)
4)更新数据:

方法一:  
Person person = em.find(Person.class,1);  
person.setName("Jack");(1).跟事务关联在一起了(2)对象处于托管状态  
方法二:  
Person person = em.find(Person.class,1);  
em.clear();//把实体管理器中的所有实体变成游离状态  
person.setName("Jack");//现在还是不可以,实体还是处于游离状态  
em.merge(person);//把游离状态中的实体bean同步到数据库  

5) 查看数据:

方法一:  
Person person = em.find(Person.class,1);//查看数据,1为对象在数据库中的id值  
方法二:  
Person person = em.getReference(Person.class,1);//没有值不出现异常,只person.getName()的时候报异常  
em.refresh(person);//进行数据库刷新,拿出最新的数据  

//加排它锁
person = em.find(Person.class,person.getId(),LockModeType.PESSIMISTIC_WRITE);

4.JPA中四种数据库状态:

(1)新建:刚new出对象来的时候
(2)托管:从数据库中查出来的时候
(3)游离(即脱管)
(4)删除

5.JPA的查询语句:

Query query = em.createQuery("select o from Person o");//必须有select o,id=等于后面不要直接写值以免sql注入
(1)匿名查询用:id
(2)未参数查询?1即:where o.id=?1//指明?的值从索引1开始
uery.getSingleResult

5.1.Java简单的示例代码

EntityManagerFactory factory = Persistence.createEntityManagerFactory("testdb");  
EntityManager em = factory.createEntityManager();  
em.getTransaction().begin();  
em.persist(new User("Jack"));  
em.getTransaction().commit();  
em.close();  
factory.close();  

5.2 JPA提供以下3种查询结果解释方法:

Transformers.ALIAS_TO_ENTITY_MAP //把输出结果转换成map   
Transformers.TO_LIST //把结果按顺序排进List   
Transformers.aliasToBean(target) //把结果通过setter方法注入到指定的对像属性中   
在JPA中Transformers的所有转换都是需要实现ResultTransformer接口。

① ALIAS_TO_ENTITY_MAP :太简单了就是把key和value直接转换到Map当中 :

public Object transformTuple(Object[] tuple, String[] aliases) {   
    Map result = new HashMap(tuple.length);   
    for ( int i=0; i<tuple.length; i++ ) {   
        String alias = aliases[i];   
        if ( alias!=null ) {   
            result.put( alias, tuple[i] );   
        }   
    } 
 
    return result;   
}  

② TO_LIST:转换过程很简单,就是把value转换成List对像:

public Object transformTuple(Object[] tuple, String[] aliases) {   
    return Arrays.asList( tuple );   
}  

③ aliasToBean:转换过程就是通过读取查询后的字段,然后通过使用setter方法注入到目标对像中 :

getSession().beginTransaction(); 
Query query = getSession().createSQLQuery("select * from user"); 
list =query.setResultTransformer(Transformers.aliasToBean(User.class)).list(); 
getSession().getTransaction().commit(); 

参考资料

原文地址:https://www.cnblogs.com/huligong1234/p/7077552.html