SQLite数据库和JPA简单介绍
SQLite数据库和JPA简单介绍
一、SQLite简单使用
SQLite是遵循ACID的关系数据库管理系统,它的处理速度很快,它的设计目标是嵌入式的,只需要几百K的内存就可以了。
1.下载SQLitehttp://www.sqlite.org/download.htmlsqlite-dll-win32-x86-201410071659.zip(294.11 KiB)sqlite-shell-win32-x86-3080600.zip解压在文件夹D:\Database\sqlite下,得到文件sqlite3.dll,sqlite3.exe参考:http://www.w3cschool.cc/sqlite/sqlite-installation.html
2.安装SQLite写批处理文件z_sqlite.bat,内容是:
@echod:cd D:\Database\sqlitecmd.exe
执行命令sqlite3,看到结果:
D:\Database\sqlite>sqlite3SQLite version 3.8.6 2014-08-15 11:46:33Enter ".help" for usage hints.Connected to a transient in-memory database.Use ".open FILENAME" to reopen on a persistent database.sqlite>
或是:
@echoPATH=%PATH%;D:\Database\sqlitecmd.exe
执行命令sqlite3,看到结果:
ECHO 处于打开状态。D:\Database>PATH=C:\PRogramData\Oracle\java\javapath;D:\Program_Files\oraclexe\app\oracle\product\10.2.0\server\bin;C:\Program Files\AMD APP\bin\x86;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\ATI Technologies\ATI.ACE\Core-Static;C:\Python27;C:\Program Files\MySQL\MySQL Server 5.5\bin;D:\Idea\config\apache-maven-3.2.3\bin;D:\Idea\config\apache-ant-1.9.4\bin;D:\Database\sqliteD:\Database>cmd.exeMicrosoft Windows [版本 6.3.9600](c) 2013 Microsoft Corporation。保留所有权利。D:\Database>sqlite3SQLite version 3.8.6 2014-08-15 11:46:33Enter ".help" for usage hints.Connected to a transient in-memory database.Use ".open FILENAME" to reopen on a persistent database.sqlite>
表明sqlite已安装。解释:不让bat文件运行命令结束后cmd窗口自动关闭,最后运行一下cmd.exe
更多疑问请参考:[SQLite 教程]:http://www.w3cschool.cc/sqlite/sqlite-installation.html
3.SQLite命令
.help 帮助.show 显示各种设置的当前值.schema 显示建表语句
sqlite> .schema sqlite_mastercreate table episodes( id integer primary key, season int, name text );
其它的命令类似于一搬的sql语句
insert into episodes values(1, 1, 'one');select * from episodes;
4.SQLite管理工具:SQLiteExpert下载:http://www.sqliteexpert.com/download.html选择免费版:SQLite Expert Personal下载的太慢了,可以选择以前的版本:http://dl.dbank.com/c0sog1u0xb
创建db文件:
D:\Database\sqlite>sqlite3 test1.dbSQLite version 3.8.6 2014-08-15 11:46:33Enter ".help" for usage hints.sqlite> sqlite3 test1.db;Error: near "sqlite3": syntax errorsqlite>
看到在D:\Database\sqlite目录下生成了一个test1.db的文件File>OpenDatabase>选择刚刚生成的db文件>确定看到数据库的文件已经导入:
二、JPA介绍Java Persistence API:简化现有的持久化开发工作和整合ORM技术结束现在的Hibernate、TopLink、JDO等ORM框架各自为营的局面面向Hibernate的API开发,会紧密的与Hibernate耦合JPA规范是由Hibernate的作者制定的
ORM映射元数据: 描述对象与表之间的映射关系Java持久化API: 执行CRUD操作查询语言: JPQL,避免程序和SQL语句的紧密耦合
设置Maven4MyEclipse:MyEclipse>Maven4MyEclipse
Installation=D:\Idea\config\apache-maven-3.2.3User Settings=D:\Idea\config\apache-maven-3.2.3\conf\settings.xmlLocal Repository=D:\Idea\maven\repository
配置文件:META-INF/persistence.xmlD:\Idea\config\hibernate-release-4.3.6.Final\lib\jpa-metamodel-generator/hibernate-jpamodelgen-4.3.6.Final.jar/persistence_2_1.xsd配置数据库的方言,以及自动建表
<?xml version="1.0" encoding="UTF-8"?><persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd "> <persistence-unit name="module1" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit></persistence>
三、SQLite作为Hibernate的数据源1.Maven配置文件:pom.xml用MyEclipse新建一个Maven的模块app1.module1配置它的pom文件:/module1/pom.xml
引入JPA的依赖:http://hibernate.org/orm/downloads/
<!-- for JPA, use hibernate-entitymanager instead of hibernate-core --><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.6.Final</version></dependency>
sqlite-jdbc引入sqlite的依赖:http://www.mvnrepository.com/artifact/org.xerial/sqlite-jdbc/3.7.2
<dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version></dependency>
处理报错:ArtifactTransferException: Failure to transfer org.xerial:sqlite-jdbc:jar:3.7.2 from http://zhanghua.1199.blog.163.com/blog/static/464498072013529936189/
对于这个包从maven中心传输到本地仓库失败,决定不会重新尝试下载jar包,直到mavne再改更新索引,或强制更新。实际的解决办法是:直接去本地仓库,把这个1.1.1的目录删除掉(因为包没有下载下来),再次刷新你的项目就中以了,或者在你的项目上右击,选择maven--->update就可以了,让maven重新下载。
删除D:\Idea\maven\repository\org\xerial文件
/module1/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>yuki.jpa.hibernate.app1</groupId> <artifactId>module1</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>module1</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- for JPA, use hibernate-entitymanager instead of hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.6.Final</version> </dependency> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version> </dependency> </dependencies></project>
2.JPA的配置文件:persistence.xmlD:\Workspaces\IntelliJ_IDEA\JavaEE_JPA\Module1\src\main\resources\META-INF\persistence.xml在这里,需要配置数据源,数据源的位置是sqlite的db文件的位置D:\Database\sqlite\test1.db数据源的用户名和密码是空字符串就可以了
/module1/src/main/java/META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?><persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd "> <persistence-unit name="module1" transaction-type="RESOURCE_LOCAL"> <class>yuki.jpa.hibernate.app1.module1.bean.Person</class> <properties> <property name="hibernate.dialect" value="com.applerao.hibernatesqlite.dialect.SQLiteDialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.connection.driver_class" value="org.sqlite.JDBC" /> <property name="hibernate.connection.url" value="jdbc:sqlite://D:/Database/sqlite/test1.db" /> <property name="hibernate.connection.username" value="" /> <property name="hibernate.connection.passWord" value="" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit></persistence>
3.SQLite的hibernate方言复制代码:https://code.google.com/p/hibernate-sqlite/source/browse/trunk/source/src/main/java/com/applerao/hibernatesqlite/dialect/SQLiteDialect.java?r=24修改报错内容:http://www.myexception.cn/open-source/1120141.html
hibernate4 替代hibernate3 的Hibernate.INTEGER的用法hibernate3 中没有了Hibernate.INTEGER的用法在Hibernate4中使用的方法是 StandardBasicTypes.INTEGER用法例如:sqlQuery.addScalar("id",StandardBasicTypes.INTEGER);
/module1/src/main/java/com/applerao/hibernatesqlite/dialect/SQLiteDialect.java
package com.applerao.hibernatesqlite.dialect;/** * https://code.google.com/p/hibernate-sqlite/source/browse/trunk/source/src/main/java/com/applerao/hibernatesqlite/dialect/SQLiteDialect.java?r=24 * http://www.myexception.cn/open-source/1120141.html * *//* * The author disclaims copyright to this source code. In place of * a legal notice, here is a blessing: * * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. * */import java.sql.Types;import org.hibernate.dialect.Dialect;import org.hibernate.dialect.function.SQLFunctionTemplate;import org.hibernate.dialect.function.StandardSQLFunction;import org.hibernate.dialect.function.VarArgsSQLFunction;import org.hibernate.type.StandardBasicTypes;public class SQLiteDialect extends Dialect { public SQLiteDialect() { super(); registerColumnType(Types.BIT, "integer"); registerColumnType(Types.TINYINT, "tinyint"); registerColumnType(Types.SMALLINT, "smallint"); registerColumnType(Types.INTEGER, "integer"); registerColumnType(Types.BIGINT, "bigint"); registerColumnType(Types.FLOAT, "float"); registerColumnType(Types.REAL, "real"); registerColumnType(Types.DOUBLE, "double"); registerColumnType(Types.NUMERIC, "numeric"); registerColumnType(Types.DECIMAL, "decimal"); registerColumnType(Types.CHAR, "char"); registerColumnType(Types.VARCHAR, "varchar"); registerColumnType(Types.LONGVARCHAR, "longvarchar"); registerColumnType(Types.DATE, "date"); registerColumnType(Types.TIME, "time"); registerColumnType(Types.TIMESTAMP, "timestamp"); registerColumnType(Types.BINARY, "blob"); registerColumnType(Types.VARBINARY, "blob"); registerColumnType(Types.LONGVARBINARY, "blob"); // registerColumnType(Types.NULL, "null"); registerColumnType(Types.BLOB, "blob"); registerColumnType(Types.CLOB, "clob"); registerColumnType(Types.BOOLEAN, "integer"); registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", "")); registerFunction("mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2")); registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING)); registerFunction("substring", new StandardSQLFunction("substr", StandardBasicTypes.STRING)); } public boolean supportsIdentityColumns() { return true; } /* * public boolean supportsInsertSelectIdentity() { return true; // As * specify in NHibernate dialect } */ public boolean hasDataTypeInIdentityColumn() { return false; // As specify in NHibernate dialect } /* * public String appendIdentitySelectToInsert(String insertString) { return * new StringBuffer(insertString.length()+30). // As specify in NHibernate * dialect append(insertString). * append("; ").append(getIdentitySelectString()). toString(); } */ public String getIdentityColumnString() { // return "integer primary key autoincrement"; return "integer"; } public String getIdentitySelectString() { return "select last_insert_rowid()"; } public boolean supportsLimit() { return true; } public String getLimitString(String query, boolean hasOffset) { return new StringBuffer(query.length() + 20).append(query).append(hasOffset ? " limit ? offset ?" : " limit ?").toString(); } public boolean supportsTemporaryTables() { return true; } public String getCreateTemporaryTableString() { return "create temporary table if not exists"; } public boolean dropTemporaryTableAfterUse() { return false; } public boolean supportsCurrentTimestampSelection() { return true; } public boolean isCurrentTimestampSelectStringCallable() { return false; } public String getCurrentTimestampSelectString() { return "select current_timestamp"; } public boolean supportsUnionAll() { return true; } public boolean hasAlterTable() { return false; // As specify in NHibernate dialect } public boolean dropConstraints() { return false; } public String getAddColumnString() { return "add column"; } public String getForUpdateString() { return ""; } public boolean supportsOuterJoinForUpdate() { return false; } public String getDropForeignKeyString() { throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect"); } public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable, String[] primaryKey, boolean referencesPrimaryKey) { throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect"); } public String getAddPrimaryKeyConstraintString(String constraintName) { throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect"); } public boolean supportsIfExistsBeforeTableName() { return true; } public boolean supportsCascadeDelete() { return false; }}
4.设置设置程序关联:控制面板\所有控制面板项\默认程序\设置默认程序\设置程序关联设置XML格式化代码时不换行:MyEclipse>FilesAndEditors>XML>XML Source>Linewidth=很大的值设置JAVA格式化代码时不换行:Java>CodeStyle>Formatter>New…>LineWrapping>SettingsForAnnotation>选择上面的选项>LineWrapPolicy=DoNotWrap
5.异常处理
没有持久化的提供者报错:javax.persistence.PersistenceException: No Persistence provider for EntityManager named module1解决:http://stackoverflow.com/questions/21975553/javax-persistence-persistenceexception-no-persistence-provider-for-entitymanage
If you're doing this from a JUnit test, and using maven,the persistence.xml should be located in src/test/resources/META-INF/persistence.xmlwhich will be put into the correct location at test execution time.The file in src/main/resources/META-INF/ is not used as it is not in the test-jar's path.
执行maven clean之后
执行maven clean后会删除运行处的persistence.xml,可以删除再添加persistence.xml,来使persistence.xml在运行的文件夹下
四、JPA实体1.自动建表<property name="hibernate.hbm2ddl.auto" value="update" />http://www.cnblogs.com/talo/articles/1662244.html
validate 加载hibernate时,验证创建数据库表结构create 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。create-drop 加载hibernate时创建,退出是删除表结构update 加载hibernate自动更新数据库结构
需要建表的类Person.java添加注解Entity,被 @Entity注解的类就是JPA的实体类,主键注解 @Id, @GeneratedValuehttp://andyj.iteye.com/blog/287827
IDENTITY: 表自增键字段,Oracle不支持这种方式AUTO: JPA自动选择合适的策略,是默认选项SEQUENCE: 通过序列产生主键,通过 @SequenceGenerator注解指定序列名,MySql不支持这种方式TABLE: 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person1.txt
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;@Entitypublic class Person { private Integer id; private String name; public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue // @GeneratedValue (strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
测试类PersonTest.java
获取实体管理器工厂,获取实体管理器,开启事务,保存,提交事务,关闭实体管理器,关闭实体管理器工厂
/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest1
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void save() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager manager = factory.createEntityManager(); manager.getTransaction().begin(); manager.persist(new Person("person1")); manager.getTransaction().commit(); manager.close(); factory.close(); } }
刷新SQliteExpert中的数据库,看到新建的表和保存的数据
2.实体类的注解
自定义表名 @Table(name="xxxPerson")自定义列的属性 @Column(length=10, nullable=false, name="personName")
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person2.txt
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name="xxxPerson")public class Person { private Integer id; private String name; public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10, nullable=false, name="personName") public String getName() { return name; } public void setName(String name) { this.name = name; }}
删除Person表,再次测试
日期类型 @Temporal(TemporalType.DATE)枚举类型 @Enumerated(EnumType.STRING)
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person3.txt
package yuki.jpa.hibernate.app1.module1.bean;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entitypublic class Person { private Integer id; private String name; private Date birthday; //1987-12-10 private Gender gender = Gender.MAN; //默认值为MAN public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10, nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Enumerated(EnumType.STRING) @Column(length=5, nullable=false/*保存枚举值要设置数据库的字段不能为空*/) public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; }}
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/Gender.java
package yuki.jpa.hibernate.app1.module1.bean;public enum Gender { MAN,WOMEN}
删除Person表,再次测试
文件或大文本数据 @Lob
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person4.txt
package yuki.jpa.hibernate.app1.module1.bean;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Lob;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entitypublic class Person { private Integer id; private String name; private Date birthday; //1987-12-10 private Gender gender = Gender.MAN; //默认值为MAN private String info; //存放大文本数据 private byte[] file; //存放文件 public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10, nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Enumerated(EnumType.STRING) @Column(length=5, nullable=false/*保存枚举值要设置数据库的字段不能为空*/) public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } @Lob public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Lob public byte[] getFile() { return file; } public void setFile(byte[] file) { this.file = file; }}
延迟加载 @Basic(fetch=FetchType.LAZY)不持久化的字段 @Transient
/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person5.txt
package yuki.jpa.hibernate.app1.module1.bean;import java.util.Date;import javax.persistence.Basic;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.FetchType;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Lob;import javax.persistence.Temporal;import javax.persistence.TemporalType;import javax.persistence.Transient;@Entitypublic class Person { private Integer id; private String name; private Date birthday; //1987-12-10 private Gender gender = Gender.MAN; //默认值为MAN private String info; //存放大文本 private byte[] file; //存放大文件,延迟加载 private String imagePath; //不持久化的字段 public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10, nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Enumerated(EnumType.STRING) @Column(length=5, nullable=false/*保存枚举值要设置数据库的字段不能为空*/) public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } @Lob public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Lob @Basic(fetch=FetchType.LAZY) //访问这个属性的时候才会加载进内存 public byte[] getFile() { return file; } public void setFile(byte[] file) { this.file = file; } @Transient public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; }}
下面使用的实体类/module1/src/main/java/yuki/jpa/hibernate/app1/module1/bean/person/Person7
package yuki.jpa.hibernate.app1.module1.bean;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Temporal;import javax.persistence.TemporalType;import javax.persistence.Transient;@Entitypublic class Person { private Integer id; private String name; private Date birthday; //1987-12-10 private Gender gender = Gender.MAN; //默认值为MAN private String imagePath; //不持久化的字段 public Person() {} public Person(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10, nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Enumerated(EnumType.STRING) @Column(length=5, nullable=false/*保存枚举值要设置数据库的字段不能为空*/) public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } @Transient public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", birthday=" + birthday + ", gender=" + gender + ", imagePath=" + imagePath + "]"; }}
3.对实体类的查找/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest2
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void getPerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager em = factory.createEntityManager();// em.getTransaction().begin(); Person person = em.find(Person.class, 1); System.out.println(person);// em.getTransaction().commit(); em.close(); factory.close(); }}
Hibernate: select person0_.id as id1_0_0_, person0_.birthday as birthday2_0_0_, person0_.gender as gender3_0_0_, person0_.name as name4_0_0_ from Person person0_ where person0_.id=?Person [id=1, name=person1, birthday=null, gender=MAN, imagePath=null]
.find和.getReference/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest4
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void getPerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager em = factory.createEntityManager();// Person person = em.find(Person.class, 1); //相当于hibernate的get Person person = em.getReference(Person.class, 1); //相当于hibernate的load// load之后返回的是代理对象,使用的是cglib动态创建字节码的技术// 如果不访问数据,是不回发生数据的加载行为的// org.hibernate.LazyInitializationException: could not initialize proxy - no session em.close(); System.out.println(person.getName()); factory.close(); } }
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.712 sec <<< FAILURE!getPerson(yuki.jpa.hibernate.app1.module1.bean.PersonTest) Time elapsed: 2.613 sec <<< ERROR!org.hibernate.LazyInitializationException: could not initialize proxy - no Session
异常在访问引用对象的属性时就会发生,即使实体管理器没有关闭/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest5
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void getPerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager em = factory.createEntityManager(); /*Person person = em.find(Person.class, 2);//null Person person = em.getReference(Person.class, 2);//javax.persistence.EntityNotFoundException System.out.println(person);*/ Person person = em.getReference(Person.class, 2); System.out.println(person.getName()); //这里出现了异常 em.close(); factory.close(); } }
at yuki.jpa.hibernate.app1.module1.bean.Person_$$_jvst586_0.getName(Person_$$_jvst586_0.java)at yuki.jpa.hibernate.app1.module1.bean.PersonTest.getPerson(PersonTest.java:19)
4.JPA实体的四种状态
new(新建)、managed(托管)、游离(脱管)、删除当一个对象与事务关联且进入托管状态时对属性进行更新,对应的数据就会同步到数据库对象的属性发生更改后,会放进jdbc的批提交里去
/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest6
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void updatePerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person person = em.find(Person.class, 2); person.setName("老张"); em.getTransaction().commit(); em.close(); factory.close(); /** * JPA对象的四种状态 * new(新建) * managed(托管) * 游离(脱管) * 删除 * * 当一个对象与事务关联且进入托管状态时, * 对属性进行更新,对应的数据就会同步到数据库 * 对象的属性发生更改后,会放进jdbc的批提交里去 * */ } }
把实体管理器中的所有实体变成游离对象 .clear()把游离对象同步回数据库 .merge(person)
/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest7
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Test;public class PersonTest { @Test public void updatePerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("module1"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person person = em.find(Person.class, 2); em.clear(); //把实体管理器中的所有实体变成游离对象 person.setName("老黎"); em.merge(person); //把游离对象同步回数据库 em.getTransaction().commit(); em.close(); factory.close(); } }
删除实体/module1/src/test/java/yuki/jpa/hibernate/app1/module1/bean/personTest/PersonTest8
package yuki.jpa.hibernate.app1.module1.bean;import javax.persistence.EntityManager;import ja