博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jpa/springdata(1)jpa
阅读量:6884 次
发布时间:2019-06-27

本文共 11169 字,大约阅读时间需要 37 分钟。

1.什么是jpa

假如学过hibernate在jpa会发现非常的简单,因为是同一个人写的,jpa是第三方orm框架的一种规范,hibernate作为jpa 的一个子集

2.需要导入的jar

这里使用的是hibernate作为orm

 待续重写整个部分

3.jpa的配置简要说明

新建--jpa项目(自动生成jpa项目的xml文件)

persistence.xml,文件的名称是固定的,然后是根据name="jpa"创建EntityManagerFactory,这个类似于c3p0连接池

org.hibernate.ejb.HibernatePersistence
com.jpa.helloworld.Item
ENABLE_SELECTIVE

 如下配置也与hibernate类似

public static void main(String[] args) {				String persistenceUnitName = "jpa";//与c3p0的配置类似的加载方法				Map
properites = new HashMap
(); properites.put("hibernate.show_sql", true); EntityManagerFactory entityManagerFactory =               //在配置文件中配置好了直接获取              //Persistence.createEntityManagerFactory(persistenceUnitName);          //在put中放置需要设置的属性,假如在xml中已经配置,那么将覆盖xml中的属性          Persistence.createEntityManagerFactory(persistenceUnitName, properites);           EntityManager entityManager = entityManagerFactory.createEntityManager();          EntityTransaction transaction = entityManager.getTransaction();          transaction.begin();//开始事务          transaction.commit();//提交事物           entityManager.close();          entityManagerFactory.close(); }

 4.注解

@Table(name="JPA_ORDERS")//对应的表名@Entity//标注为实体类public class Dept {    private Integer id;    private String deptName;    @GeneratedValue/*获取主键的方式,主键id的描述,在hibernate中,以及mybatis中的resultmap的都是描述为id标签, 这里获取主键的方式有IDENTITY:采用数据库 ID自增长的方式来自增主键段,Oracle 不支持这种方式;AUTO: JPA自动选择合适的策略, 是默认选项(因为是默认的选项所以也可以不写);SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式,TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。@GeneratedValue(strategy=GenerationType.AUTO),GenerationType.TABLE有些特殊但是避免了数据库切换不兼容的问题    @TableGenerator(name="ID_GENERATOR",   //与generator="ID_GENERATOR"的值一致    table="jpa_id_generators", //数据库表的名称,这里是三列,id,PK_NAME,PK_VALUE    pkColumnName="PK_NAME",//数据库表的对应的列的名称    pkColumnValue="CUSTOMER_ID",//向对应列的名称的值    valueColumnName="PK_VALUE",//数据库表的对应的列的名称    allocationSize=100)//这里设置的值,PK_VALUE设置为100,每次id自增100    @GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GENERATOR")   */	@Id	public Integer getId() {		return id;	}       	public void setId(Integer id) {		this.id = id;	}	@Column(name="DEPT_NAME")/*对应数据库的名称,也是新建数据库的名称,假如数据库的名称与属性的名称一致,那么这类的注解也可以默认不写,   在所有的默认的get方法上会默认的添加@Basic注解,假如在没有set方法的前提下会报错,假如现在有一个get方法,但是不需要与数据库相关联,   那么在get方法上使用@Transient,jap处理注解在类方法上的注解,其余都在get方法上,Column还具有以下一些属性 ,unique(唯一)  、   nullable(不能为null) 、length (长度)等, @Column(name="LAST_NAME",length=50,nullable=false)*/	public String getDeptName() {		return deptName;	} 	public void setDeptName(String deptName) {		this.deptName = deptName;	}        @Transient         public  void getInfo() {		System.out.println(111);	}                }

 其他注解

 @Temporal  //时间匹配的格式

例如

@Temporal(TemporalType.DATE)//可选TemporalType.TIME,TemporalType.DATE,TemporalType.TIMESTAMPpublic java.util.Date getDate() {	return date;}

5.常用api

1)EntityManagerFactory的常用方法

createEntityManager():用于创建实体管理器对象实例。

createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map 参数用于提供 EntityManager 的属性。

isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭。

close():关闭 EntityManagerFactory 。 EntityManagerFactory 关闭后将释放所有资源,isOpen()方法测试将返回 false,其它方法将不能调用,否则将导致IllegalStateException异常。

2)EntityManager的常用方法

1> find方法(同hibernate的get方法,用法基本一致)

Department dept = entityManager.find(Department.class, 1);//1表示更具id查询的

2> getReference方法(类似于hibernate的load方法,用法基本一致,延时加载,使用代理类)

3> persist方法(类似hibernate的persist方法,没有save方法,不能设置id)

entityManager.persist(mgr);

4> remove方法(类似于hibernate的delete方法)

5> merge方法(类似于updateorsave方法,但是又不同,在updateorsave方法中的session不能同时关联两个oid,而merge的entityManager可以这么去做)

customer.setId(4);Customer customer2 = entityManager.find(Customer.class, 4);entityManager.merge(customer);System.out.println(customer == customer2); //false

6> flush方法(类似hibernate的flush,不会提交事务,只是一个sql语句,事务没有提交,那么数据库的数值还是没变)

7> clear方法(类似hibernate的clear方法,清除一级缓存)

8> contains (Object entity) 方法 (判断entity实例是否属于当前持久上下文环境管理)

9> isOpen方法(判断实体管理器是否处于打开状态)

10> getTransaction方法(获取事物)

11> close方法(关闭)

12>refresh方法(类似hibernate的refresh方法,将持久化刷新到缓存)

13>createQuery(String  sql) 方法(类似hibernate的createQuery方法)

14>createNativeQuery (String sqlString)方法()使用规范的sql语句

15>getTransaction方法(获取事物)

3)EntityTransaction的方法

1)begin ()用于启动一个事务,此后的多个数据库操作将作为整体被提交或撤消。若这时事务已启动则会抛出 IllegalStateException 异常。

2)commit ()用于提交当前事务。即将事务启动以后的所有数据库更新操作持久化至数据库中。

3)rollback ()撤消(回滚)当前事务。即撤消事务启动后的所有数据库更新操作,从而不对数据库产生影响。

4)setRollbackOnly ()使当前事务只能被撤消。

5)getRollbackOnly ()查看当前事务是否设置了只能撤消标志。

6)isActive ()查看当前事务是否是活动的。如果返回true则不能调用begin方法,否则将抛出 IllegalStateException 异常;如果返回 false 则不能调用 commit、rollback、setRollbackOnly 及 getRollbackOnly 方法,否则将抛出 IllegalStateException 异常

 

5.关系映射

1)1对1

@JoinColumn(name="MGR_ID", unique=true)//对应列,unique=true满足唯一    @OneToOne(fetch=FetchType.LAZY)//fetch=FetchType.LAZY延迟加载,存在的异常类似hibernate的load    public Manager getMgr() {        return mgr;    }//单向一对一    @OneToOne(mappedBy="mgr")//mappedBy="mgr"表示维护的一端,没写默认都是对应主键的外键关联    public Department getDept() {        return dept;    }//双向一对一

2)单向1对多

@JoinColumn(name="CUSTOMER_ID")    @OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")//cascade={CascadeType.REMOVE}级联,mappedBy="customer"维护的一端    public Set
getOrders() { return orders; }

3)单向多对1

@JoinColumn(name="CUSTOMER_ID")    @ManyToOne(fetch=FetchType.LAZY)    public Customer getCustomer() {        return customer;    }

4)双向1对多

2)和3)一起

5)多对多

@ManyToMany(mappedBy="categories")    public Set
getItems() { return items; }@JoinTable(name="ITEM_CATEGORY", //@JoinTable 来映射中间表,name 指向中间表的名字,多对多是基于外表的 joinColumns={@JoinColumn(name="ITEM_ID", referencedColumnName="ID")},//joinColumns 映射当前类所在的表在中间表中的外键,name 指定外键列的列名,referencedColumnName 指定外键列关联当前表的哪一列,inverseJoinColumns={@JoinColumn(name="CATEGORY_ID", referencedColumnName="ID")})//inverseJoinColumns映射关联的类所在中间表的外键 @ManyToMany public Set
getCategories() { return categories; }

6.二级缓存

   <!--配置二级缓存的策略

        ALL:所有的实体类都被缓存
        NONE:所有的实体类都不被缓存.
        ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
        DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
        UNSPECIFIED:默认值,JPA 产品默认值将被使用
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>//基本类似hibernate,原理和hibernate和mybatis差不多,前提需要开启被管理的orm框架的二级缓存

 

7.jpql和hibernate的hql的语法基本类似

1)createQuery方法:

public void testPartlyProperties(){        String jpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id > ?";/*Customer c,根据Customer的注释可以找到表名,new Customer(c.lastName, c.age), 根据查询结果进行填充*/        List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();        System.out.println(result); }

2)createNamedQuery方法//使用 @NamedQuery 标记的查询语句

public void testNamedQuery(){

        Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
        Customer customer = (Customer) query.getSingleResult();
        System.out.println(customer);
}
@NamedQuery(name="testNamedQuery", query="FROM Customer c WHERE c.id = ?")//使用这个之后才能使用createNamedQuery
@Cacheable(true)//开启缓存,兼与jpa的二级缓存策略
@Table(name="JPA_CUTOMERS")//表名
@Entity//实体
public class Customer {}

3)createNativeQuery方法//使用规范的sql

public void testNativeQuery(){

        String sql = "SELECT age FROM jpa_cutomers WHERE id = ?";
        Query query = entityManager.createNativeQuery(sql).setParameter(1, 3);
        Object result = query.getSingleResult();
        System.out.println(result);
}

4)查询缓存

String jpql = "FROM Customer c WHERE c.age > ?";

Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);/*需要开启二级缓存(见jpa配置),在二级缓存中查找,假如解析后的sql语句一致,不会发送sql,直接使用缓存中的数据*/

5)排序与分组

分组

String jpql = "SELECT o.customer FROM Order o GROUP BY o.customer HAVING count(o.id) >= 2;

List<Customer> customers = entityManager.createQuery(jpql).getResultList();

排序

String jpql = "FROM Customer c WHERE c.age > ? ORDER BY c.age DESC";

Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);

6)连表查询

String jpql = "FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?";  //其他一致,内联接,右连接

Customer customer = (Customer) entityManager.createQuery(jpql).setParameter(1, 12).getSingleResult();

7)子查询

    String jpql = "SELECT o FROM Order o WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName = ?)";

    Query query = entityManager.createQuery(jpql).setParameter(1, "YY");

8)字符串处理函数:

concat(String s1, String s2):字符串合并/连接函数。

substring(String s, int start, int length):取字串函数。

trim([leading|trailing|both,] [char c,] String s):从字符串中去掉首/尾指定的字符或空格。

lower(String s):将字符串转换成小写形式。

upper(String s):将字符串转换成大写形式。

length(String s):求字符串的长度。

locate(String s1, String s2[, int start]):从第一个字符串中查找第二个字符串(子串)出现的位置。若未找到则返回0。

备注:其它基本上与hql一致,个人还是写sql写的比较多,然后使用类的方式也有//类找表

 

8.spring整合jpa

         
true
true
update

 测试

public class Test {	private  static ApplicationContext  ctx=null;	{		ctx= new ClassPathXmlApplicationContext("application.xml");	}		@org.junit.Test	public  void   testC3p0(){		ComboPooledDataSource bean = ctx.getBean(ComboPooledDataSource.class);		System.out.println(bean);	}		@org.junit.Test	public  void testEntity() throws SQLException{		LocalContainerEntityManagerFactoryBean lcemf = ctx.getBean(LocalContainerEntityManagerFactoryBean.class);		DataSource dataSource = lcemf.getDataSource();		Connection connection = dataSource.getConnection();		System.out.println(connection);	}}@org.junit.Test	public  void testEntity() throws SQLException{		LocalContainerEntityManagerFactoryBean lcemf = ctx.getBean(LocalContainerEntityManagerFactoryBean.class);//		DataSource dataSource = lcemf.getDataSource();//		Class
entityManagerInterface = lcemf.getEntityManagerInterface(); EntityManagerFactory en = lcemf.getNativeEntityManagerFactory(); EntityManager manager = en.createEntityManager(); EntityTransaction transaction = manager.getTransaction(); transaction.begin(); Person person = new Person(); person.setBrith(new Date()); person.setEamil("11@11"); person.setLastName("john"); manager.persist(person); transaction.commit(); manager.close(); en.close();// if(lcemf instanceof EntityManager){//false// System.out.println(true);// }// Connection connection = dataSource.getConnection();// System.out.println(connection); }

综上所述有以下的结论

@Repositorypublic class PersonDao {	@PersistenceContext//上述测试类的一系列代码,应为LocalContainerEntityManagerFactoryBean不是EntityManager	private EntityManager entityManager;		public void save(Person person){		entityManager.persist(person);	}	}

 

转载于:https://www.cnblogs.com/gg128/p/9733802.html

你可能感兴趣的文章
Source Insight 常用设置
查看>>
android anr什么意思?
查看>>
视频: DroidPilot - 增强多应用集成测试 - V2.1.0 (新)
查看>>
python实现逐行替换超大文件中的字符串
查看>>
软件工程例子
查看>>
python全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)...
查看>>
异步编程与多线程编程的联系和区别
查看>>
单例模式(Singleton Pattern)
查看>>
SQL Server
查看>>
pre标签内文本自动换行
查看>>
RCF的简单使用教程以及什么是回调函数
查看>>
java的Pattern类
查看>>
2019.2.18 区块链论文翻译
查看>>
HDU-统计难题
查看>>
python的PIL模块安装
查看>>
数据结构与算法(0)-四则运算
查看>>
ASP.NET-FineUI开发实践-17
查看>>
BETA 版冲刺前准备
查看>>
微信小程序简单入门2
查看>>
15个NoSql数据库
查看>>