使用hibernate的hql查询emp表出现的不是数据

panda-dragon 2017-01-11 04:23:42


使用hibernate的hql查询emp表出现的不是数据
...全文
104 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
李德胜1995 2017-01-11
  • 打赏
  • 举报
回复
引用 6 楼 qq_24282623 的回复:
重写tostring 报错 [quote=引用 5 楼 pany1209 的回复:] [quote=引用 4 楼 qq_24282623 的回复:] 重写tostring 报错
程序递归太深,栈溢出[/quote] 请问怎么解决啊 [/quote]把toString()去掉吧。。打印几个属性出来看看就得了
panda-dragon 2017-01-11
  • 打赏
  • 举报
回复
重写tostring 报错
引用 5 楼 pany1209 的回复:
[quote=引用 4 楼 qq_24282623 的回复:] 重写tostring 报错
程序递归太深,栈溢出[/quote] 请问怎么解决啊
李德胜1995 2017-01-11
  • 打赏
  • 举报
回复
引用 4 楼 qq_24282623 的回复:
重写tostring 报错
程序递归太深,栈溢出
panda-dragon 2017-01-11
  • 打赏
  • 举报
回复


重写tostring 报错
panda-dragon 2017-01-11
  • 打赏
  • 举报
回复
不是tostrng的原因,在Emp.java中重写直接报错
  • 打赏
  • 举报
回复
你要重写toString()方法啊
李德胜1995 2017-01-11
  • 打赏
  • 举报
回复
你要重写toString()方法啊
Hibernate注释大全收藏 声明实体Bean @Entity public class Flight implements Serializable { Long id; @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } } @Entity 注解将一个类声明为实体 Bean, @Id 注解声明了该实体Bean的标识属性。 Hibernate 可以对类的属性或者方法进行注解。属性对应field类别,方法的 getXxx()对应property类别。 定义 通过 @Table 为实体Bean指定对应数据,目录和schema的名字。 @Entity @Table(name="tbl_sky") public class Sky implements Serializable { ... @Table 注解包含一个schema和一个catelog 属性,使用@UniqueConstraints 可以定义的唯一约束。 @Table(name="tbl_sky", uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})} ) 上述代码在 "month" 和 "day" 两个 field 上加上 unique constrainst. @Version 注解用于支持乐观锁版本控制。 @Entity public class Flight implements Serializable { ... @Version @Column(name="OPTLOCK") public Integer getVersion() { ... } } version属性映射到 "OPTLOCK" 列,entity manager 使用这个字段来检测冲突。 一般可以用 数字 或者 timestamp 类型来支持 version. 实体Bean中所有非static 非 transient 属性都可以被持久化,除非用@Transient注解。 默认情况下,所有属性都用 @Basic 注解。 public transient int counter; //transient property private String firstname; //persistent property @Transient String getLengthInMeter() { ... } //transient property String getName() {... } // persistent property @Basic int getLength() { ... } // persistent property @Basic(fetch = FetchType.LAZY) String getDetailedComment() { ... } // persistent property @Temporal(TemporalType.TIME) java.util.Date getDepartureTime() { ... } // persistent property @Enumerated(EnumType.STRING) Starred getNote() { ... } //enum persisted as String in database 上述代码中 counter, lengthInMeter 属性将忽略不被持久化,而 firstname, name, length 被定义为可持久化和可获取的。 @TemporalType.(DATE,TIME,TIMESTAMP) 分别Map java.sql.(Date, Time, Timestamp). @Lob 注解属性将被持久化为 Blog 或 Clob 类型。具体的java.sql.Clob, Character[], char[] 和 java.lang.String 将被持久化为 Clob 类型. java.sql.Blob, Byte[], byte[] 和 serializable type 将被持久化为 Blob 类型。 @Lob public String getFullText() { return fullText; // clob type } @Lob public byte[] getFullCode() { return fullCode; // blog type } @Column 注解将属性映射到列。 @Entity public class Flight implements Serializable { ... @Column(updatable = false, name = "flight_name", nullable = false, length=50) public String getName() { ... } 定义 name 属性映射到 flight_name column, not null, can't update, length equal 50 @Column( name="columnName"; (1) 列名 boolean unique() default false; (2) 是否在该列上设置唯一约束 boolean nullable() default true; (3) 列可空? boolean insertable() default true; (4) 该列是否作为生成 insert语句的一个列 boolean updatable() default true; (5) 该列是否作为生成 update语句的一个列 String columnDefinition() default ""; (6) 默认值 String table() default ""; (7) 定义对应的(deault 是主) int length() default 255; (8) 列长度 int precision() default 0; // decimal precision (9) decimal精度 int scale() default 0; // decimal scale (10) decimal长度 嵌入式对象(又称组件)也就是别的对象定义的属性 组件类必须在类一级定义 @Embeddable 注解。在特定的实体关联属性上使用 @Embeddable 和 @AttributeOverride 注解可以覆盖该属性对应的嵌入式对象的列映射。 @Entity public class Person implements Serializable { // Persistent component using defaults Address homeAddress; @Embedded @AttributeOverrides( { @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ), @AttributeOverride(name="name", column = @Column(name="bornCountryName") ) } ) Country bornIn; ... } @Embeddable public class Address implements Serializable { String city; Country nationality; //no overriding here } @Embeddable public class Country implements Serializable { private String iso2; @Column(name="countryName") private String name; public String getIso2() { return iso2; } public void setIso2(String iso2) { this.iso2 = iso2; } public String getName() { return name; } public void setName(String name) { this.name = name; } ... } Person 类定义了 Address 和 Country 对象,具体两个类实现见上。 无注解属性默认值: • 属性为简单类型,则映射为 @Basic • 属性对应的类型定义了 @Embeddable 注解,则映射为 @Embedded • 属性对应的类型实现了Serializable,则属性被映射为@Basic并在一个列中保存该对象的serialized版本。 • 属性的类型为 java.sql.Clob or java.sql.Blob, 则映射到 @Lob 对应的类型。 映射主键属性 @Id 注解可将实体Bean中某个属性定义为主键,使用@GenerateValue注解可以定义该标识符的生成策略。 • AUTO - 可以是 identity column, sequence 或者 table 类型,取决于不同底层的数据库 • TABLE - 使用table保存id值 • IDENTITY - identity column • SEQUENCE - seque nce @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE") public Integer getId() { ... } @Id @GeneratedValue(strategy=GenerationType.IDENTITY) public Long getId() { ... } AUTO 生成器,适用与可移值的应用,多个@Id可以共享同一个 identifier生成器,只要把generator属性设成相同的值就可以。通过@SequenceGenerator 和 @TableGenerator 可以配置不同的 identifier 生成器。 //and the annotation equivalent @javax.persistence.TableGenerator( name="EMP_GEN", table="GENERATOR_TABLE", pkColumnName = "key", valueColumnName = "hi" pkColumnValue="EMP", allocationSize=20 ) //and the annotation equivalent @javax.persistence.SequenceGenerator( name="SEQ_GEN", sequenceName="my_sequence", allocationSize=20 ) The next example shows the definition of a sequence generator in a class scope: @Entity @javax.persistence.SequenceGenerator( name="SEQ_STORE", sequenceName="my_sequence" ) public class Store implements Serializable { private Long id; @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE") public Long getId() { return id; } } Store类使用名为my_sequence的sequence,并且SEQ_STORE生成器对于其他类是不可见的。 通过下面语法,你可以定义组合键。 • 将组件类注解为 @Embeddable, 并将组件的属性注解为 @Id • 将组件的属性注解为 @EmbeddedId • 将类注解为 @IdClass,并将该实体中所有主键的属性都注解为 @Id @Entity @IdClass(FootballerPk.class) public class Footballer { //part of the id key @Id public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } //part of the id key @Id public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getClub() { return club; } public void setClub(String club) { this.club = club; } //appropriate equals() and hashCode() implementation } @Embeddable public class FootballerPk implements Serializable { //same name and type as in Footballer public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } //same name and type as in Footballer public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } //appropriate equals() and hashCode() implementation } @Entity @AssociationOverride( name="id.channel", joinColumns = @JoinColumn(name="chan_id") ) public class TvMagazin { @EmbeddedId public TvMagazinPk id; @Temporal(TemporalType.TIME) Date time; } @Embeddable public class TvMagazinPk implements Serializable { @ManyToOne public Channel channel; public String name; @ManyToOne public Presenter presenter; } 映射继承关系 EJB支持3种类型的继承。 • Table per Class Strategy: the element in Hibernate 每个类一张 • Single Table per Class Hierarchy Strategy: the element in Hibernate 每个类层次结构一张 • Joined Subclass Strategy: the element in Hibernate 连接的子类策略 @Inheritance 注解来定义所选的之类策略。 每个类一张 @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Flight implements Serializable { 有缺点,如多态查询或关联。Hibernate 使用 SQL Union 查询来实现这种策略。 这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。 每个类层次结构一张 @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="planetype", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue("Plane") public class Plane { ... } @Entity @DiscriminatorValue("A320") public class A320 extends Plane { ... } 整个层次结构中的所有父类和子类属性都映射到同一个中,他们的实例通过一个辨别符列(discriminator)来区分。 Plane 是父类。@DiscriminatorColumn 注解定义了辨别符列。对于继承层次结构中的每个类, @DiscriminatorValue 注解指定了用来辨别该类的值。 辨别符列名字默认为 DTYPE,其默认值为实体名。其类型为DiscriminatorType.STRING。 连接的子类 @Entity @Inheritance(strategy=InheritanceType.JOINED) public class Boat implements Serializable { ... } @Entity public class Ferry extends Boat { ... } @Entity @PrimaryKeyJoinColumn(name="BOAT_ID") public class AmericaCupClass extends Boat { ... } 以上所有实体使用 JOINED 策略 Ferry和Boat class使用同名的主键关联(eg: Boat.id = Ferry.id), AmericaCupClass 和 Boat 关联的条件为 Boat.id = AmericaCupClass.BOAT_ID. 从父类继承的属性 @MappedSuperclass public class BaseEntity { @Basic @Temporal(TemporalType.TIMESTAMP) public Date getLastUpdate() { ... } public String getLastUpdater() { ... } ... } @Entity class Order extends BaseEntity { @Id public Integer getId() { ... } ... } 继承父类的一些属性,但不用父类作为映射实体,这时候需要 @MappedSuperclass 注解。 上述实体映射到数据库中的时候对应 Order 实体Bean, 其具有 id, lastUpdate, lastUpdater 三个属性。如果没有@MappedSuperclass 注解,则父类中属性忽略,这是 Order 实体 Bean 只有 id 一个属性。 映射实体Bean的关联关系 一对一 使用 @OneToOne 注解可以建立实体Bean之间的一对一关系。一对一关系有3种情况。 • 关联的实体都共享同样的主键。 @Entity public class Body { @Id public Long getId() { return id; } @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn public Heart getHeart() { return heart; } ... } @Entity public class Heart { @Id public Long getId() { ...} } 通过@PrimaryKeyJoinColumn 注解定义了一对一的关联关系。 多对一 使用 @ManyToOne 注解定义多对一关系。 @Entity() public class Flight implements Serializable { @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinColumn(name="COMP_ID") public Company getCompany() { return company; } ... } 其中@JoinColumn 注解是可选的,关键字段默认值和一对一关联的情况相似。列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。本例中为company_id,因为关联的属性是company, Company的主键为 id. @ManyToOne 注解有个targetEntity属性,该参数定义了目标实体名。通常不需要定义,大部分情况为默认值。但下面这种情况则需要 targetEntity 定义(使用接口作为返回值,而不是常用的实体)。 @Entity() public class Flight implements Serializable { @ManyToOne(cascade= {CascadeType.PERSIST,CascadeType.MERGE},targetEntity= CompanyImpl.class) @JoinColumn(name="COMP_ID") public Company getCompany() { return company; } ... } public interface Company { ... 多对一也可以通过关联的方式来映射,通过 @JoinTable 注解可定义关联。该关联包含指回实体的外键(通过@JoinTable.joinColumns)以及指向目标实体的外键(通过@JoinTable.inverseJoinColumns). @Entity() public class Flight implements Serializable { @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinTable(name="Flight_Company", joinColumns = @JoinColumn(name="FLIGHT_ID"), inverseJoinColumns = @JoinColumn(name="COMP_ID") ) public Company getCompany() { return company; } ... } 集合类型 一对多 @OneToMany 注解可定义一对多关联。一对多关联可以是双向的。 双向 规范中多对一端几乎总是双向关联中的主体(owner)端,而一对多的关联注解为 @OneToMany(mappedBy=) @Entity public class Troop { @OneToMany(mappedBy="troop") public Set getSoldiers() { ... } @Entity public class Soldier { @ManyToOne @JoinColumn(name="troop_fk") public Troop getTroop() { ... } Troop 通过troop属性和Soldier建立了一对多的双向关联。在 mappedBy 端不必也不能定义任何物理映射。 单向 @Entity public class Customer implements Serializable { @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn(name="CUST_ID") public Set getTickets() { ... } @Entity public class Ticket implements Serializable { ... //no bidir } 一般通过连接来实现这种关联,可以通过@JoinColumn注解来描述这种单向关联关系。上例 Customer 通过 CUST_ID 列和 Ticket 建立了单向关联关系。 通过关联来处理单向关联 @Entity public class Trainer { @OneToMany @JoinTable( name="TrainedMonkeys", joinColumns = @JoinColumn( name="trainer_id"), inverseJoinColumns = @JoinColumn( name="monkey_id") ) public Set getTrainedMonkeys() { ... } @Entity public class Monkey { ... //no bidir } 通过关联来处理单向一对多关系是首选,这种关联通过 @JoinTable 注解来进行描述。上例子中 Trainer 通过TrainedMonkeys和Monkey建立了单向关联关系。其中外键trainer_id关联到Trainer(joinColumns)而外键monkey_id关联到Monkey(inverseJoinColumns). 默认处理机制 通过连接来建立单向一对多关联不需要描述任何物理映射,名由一下3个部分组成,主(owner table)名 + 下划线 + 从(the other side table)名。指向主的外键名:主名+下划线+主主键列名 指向从的外键定义为唯一约束,用来示一对多的关联关系。 @Entity public class Trainer { @OneToMany public Set getTrainedTigers() { ... } @Entity public class Tiger { ... //no bidir } 上述例子中 Trainer 和 Tiger 通过 Trainer_Tiger 连接建立单向关联关系。其中外键 trainer_id 关联到 Trainer,而外键 trainedTigers_id 关联到 Tiger 。 多对多 通过 @ManyToMany 注解定义多对多关系,同时通过 @JoinTable 注解描述关联和关联条件。其中一端定义为 owner, 另一段定义为 inverse(对关联进行更新操作,这段被忽略)。 @Entity public class Employer implements Serializable { @ManyToMany( targetEntity=org.hibernate.test.metadata.manytomany.Employee.class, cascade={CascadeType.PERSIST, CascadeType.MERGE} ) @JoinTable( name="EMPLOYER_EMPLOYEE", joinColumns=@JoinColumn(name="EMPER_ID"), inverseJoinColumns=@JoinColumn(name="EMPEE_ID") ) public Collection getEmployees() { return employees; } ... } @Entity public class Employee implements Serializable { @ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "employees", targetEntity = Employer.class ) public Collection getEmployers() { return employers; } } 默认值: 关联名:主名 + 下划线 + 从名;关联到主的外键:主名 + 下划线 + 主中主键列名;关联到从的外键名:主中用于关联的属性名 + 下划线 + 从的主键列名。 用 cascading 实现传播持久化(Transitive persistence) cascade 属性接受值为 CascadeType 数组,其类型如下: • CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed 如果一个实体是受管状态,或者当 persist() 函数被调用时,触发级联创建(create)操作。 • CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed 如果一个实体是受管状态,或者当 merge() 函数被调用时,触发级联合并(merge)操作。 • CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called 当 delete() 函数被调用时,触发级联删除(remove)操作。 • CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called 当 refresh() 函数被调用时,出发级联更新(refresh)操作。 • CascadeType.ALL: all of the above 以上全部 映射二级列 使用类一级的 @SecondaryTable 和 @SecondaryTables 注解可以实现单个实体到多个的映射。使用 @Column 或者 @JoinColumn 注解中的 table 参数可以指定某个列所属的特定。 @Entity @Table(name="MainCat") @SecondaryTables({ @SecondaryTable(name="Cat1", pkJoinColumns={ @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")}), @SecondaryTable(name="Cat2", uniqueConstraints={ @UniqueConstraint(columnNames={"storyPart2"})}) }) public class Cat implements Serializable { private Integer id; private String name; private String storyPart1; private String storyPart2; @Id @GeneratedValue public Integer getId() { return id; } public String getName() { return name; } @Column(table="Cat1") public String getStoryPart1() { return storyPart1; } @Column(table="Cat2") public String getStoryPart2() { return storyPart2; } 上述例子中, name 保存在 MainCat 中,storyPart1保存在 Cat1 中,storyPart2 保存在 Cat2 中。 Cat1 通过外键 cat_id 和 MainCat 关联, Cat2 通过 id 列和 MainCat 关联。对storyPart2 列还定义了唯一约束。 映射查询 使用注解可以映射 EJBQL/HQL 查询,@NamedQuery 和 @NamedQueries 是可以使用在类级别或者JPA的XML文件中的注解。 select p from Plane p ... ... @Entity @NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date") public class Night { ... } public class MyDao { doStuff() { Query q = s.getNamedQuery("night.moreRecentThan"); q.setDate( "date", aMonthAgo ); List results = q.list(); ... } ... } 可以通过定义 QueryHint 数组的 hints 属性为查询提供一些 hint 信息。下图是一些 Hibernate hints: 映射本地化查询 通过@SqlResultSetMapping 注解来描述 SQL 的 resultset 结构。如果定义多个结果集映射,则用 @SqlResultSetMappings。 @NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, " + " night.night_date, area.id aid, night.area_id, area.name " + "from Night night, Area area where night.area_id = area.id", resultSetMapping="joinMapping") @SqlResultSetMapping( name="joinMapping", entities={ @EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = { @FieldResult(name="id", column="nid"), @FieldResult(name="duration", column="night_duration"), @FieldResult(name="date", column="night_date"), @FieldResult(name="area", column="area_id"), discriminatorColumn="disc" }), @EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = { @FieldResult(name="id", column="aid"), @FieldResult(name="name", column="name") }) } ) 上面的例子,名为“night&area”的查询和 "joinMapping"结果集映射对应,该映射返回两个实体,分别为 Night 和 Area, 其中每个属性都和一个列关联,列名通过查询获取。 @Entity @SqlResultSetMapping(name="implicit", entities=@EntityResult( entityClass=org.hibernate.test.annotations.@NamedNativeQuery( name="implicitSample", query="select * from SpaceShip", resultSetMapping="implicit") public class SpaceShip { private String name; private String model; private double speed; @Id public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name="model_txt") public String getModel() { return model; } public void setModel(String model) { this.model = model; } public double getSpeed() { return speed; } public void setSpeed(double speed) { this.speed = speed; } } 上例中 model1 属性绑定到 model_txt 列,如果和相关实体关联设计到组合主键,那么应该使用 @FieldResult 注解来定义每个外键列。@FieldResult的名字组成:定义这种关系的属性名字 + "." + 主键名或主键列或主键属性。 @Entity @SqlResultSetMapping(name="compositekey", entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class, fields = { @FieldResult(name="name", column = "name"), @FieldResult(name="model", column = "model"), @FieldResult(name="speed", column = "speed"), @FieldResult(name="captain.firstname", column = "firstn"), @FieldResult(name="captain.lastname", column = "lastn"), @FieldResult(name="dimensions.length", column = "length"), @FieldResult(name="dimensions.width", column = "width") }), columns = { @ColumnResult(name = "surface"), @ColumnResult(name = "volume") } ) @NamedNativeQuery(name="compositekey", query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as resultSetMapping="compositekey") }) 如果查询返回的是单个实体,或者打算用系统默认的映射,这种情况下可以不使用 resultSetMapping,而使用resultClass属性,例如: @NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultClass=SpaceShip.class) public class SpaceShip { Hibernate 独有的注解扩展 Hibernate 提供了与其自身特性想吻合的注解,org.hibernate.annotations package包含了这些注解。 实体 org.hibernate.annotations.Entity 定义了 Hibernate 实体需要的信息。 • mutable: whether this entity is mutable or not 此实体是否可变 • dynamicInsert: allow dynamic SQL for inserts 用动态SQL新增 • dynamicUpdate: allow dynamic SQL for updates 用动态SQL更新 • selectBeforeUpdate: Specifies that Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified.指明Hibernate从不运行SQL Update,除非能确定对象已经被修改 • polymorphism: whether the entity polymorphism is of PolymorphismType.IMPLICIT (default) or PolymorphismType.EXPLICIT 指出实体多态是 PolymorphismType.IMPLICIT(默认)还是PolymorphismType.EXPLICIT • optimisticLock: optimistic locking strategy (OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY or OptimisticLockType.ALL) 乐观锁策略 标识符 @org.hibernate.annotations.GenericGenerator和@org.hibernate.annotations.GenericGenerators允许你定义hibernate特有的标识符。 @Id @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy = "uuid") public String getId() { @Id @GeneratedValue(generator="hibseq") @GenericGenerator(name="hibseq", strategy = "seqhilo", parameters = { @Parameter(name="max_lo", value = "5"), @Parameter(name="sequence", value="heybabyhey") } ) public Integer getId() { 新例子 @GenericGenerators( { @GenericGenerator( name="hibseq", strategy = "seqhilo", parameters = { @Parameter(name="max_lo", value = "5"), @Parameter(name="sequence", value="heybabyhey") } ), @GenericGenerator(...) } ) 自然ID 用 @NaturalId 注解标识 公式 让数据库而不是JVM进行计算。 @Formula("obj_length * obj_height * obj_width") public long getObjectVolume() 索引 通过在列属性(property)上使用@Index注解,可以指定特定列的索引,columnNames属性(attribute)将随之被忽略。 @Column(secondaryTable="Cat1") @Index(name="story1index") public String getStoryPart1() { return storyPart1; } 辨别符 @Entity @DiscriminatorFormula("case when forest_type is null then 0 else forest_type end") public class Forest { ... } 过滤 查询 ... • 其中一个实体通过外键关联到另一个实体的主键。注:一对一,则外键必须为唯一约束。 @Entity public class Customer implements Serializable { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name="passport_fk") public Passport getPassport() { ... } @Entity public class Passport implements Serializable { @OneToOne(mappedBy = "passport") public Customer getOwner() { ... } 通过@JoinColumn注解定义一对一的关联关系。如果没有@JoinColumn注解,则系统自动处理,在主中将创建连接列,列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。上例为 passport_id, 因为Customer 中关联属性为 passport, Passport 的主键为 id. • 通过关联来保存两个实体之间的关联关系。注:一对一,则关联每个外键都必须是唯一约束。 @Entity public class Customer implements Serializable { @OneToOne(cascade = CascadeType.ALL) @JoinTable(name = "CustomerPassports", joinColumns = @JoinColumn(name="customer_fk"), inverseJoinColumns = @JoinColumn(name="passport_fk") ) public Passport getPassport() { ... } @Entity public class Passport implements Serializable { @OneToOne(mappedBy = "passport") public Customer getOwner() { ... } Customer 通过 CustomerPassports 关联和 Passport 关联。该关联通过 passport_fk 外键指向 Passport ,该信心定义为 inverseJoinColumns 的属性值。 通过 customer_fk 外键指向 Customer ,该信息定义为 joinColumns 属性值。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tangcx/archive/2009/05/05/4152320.aspx
Hibernate的检索方式:(查询/加载) 1. 通过OID加载 session.get(Users.class, 1); * 2. 通过HQL/SQL 检索 hibernate query language (面向对象的查询语言) * a) 不再操纵,它操纵的是持久化类的对象 b) 面向对象的 3. QBC ( query by criteria ) 更加面向对象 4. QBE ( query by Example ) 5. SQL Hibernate的检索策略: 1. 延迟检索(加载)映射文件中改变lazy a) Lazy的取值: i. Many-to-one 1. false 2. proxy 3. no-proxy ii. set 一对多 1. true   2. false   3. extra 根据对set容器的不同,可以产生高效的sql访问数据库 2. 批量检索:batch-size=3 a) 可以使用批量检索: b) 在内存中,如果有多个set(代理)容器需要初始化, 则当访问任何一个代理set容器时,一次初始化n个set容器,减少sql语句; c) 产生的语句是:select * from ….. where FK in (?,?,?... …n); 3. 迫切(fetch)左外连接检索: a) 在映射文件中设置:fetch(抓取) i. Select 什么都不做 ii. Subselect 当访问内存中的一个代理容器时,一次将所有的set容器用一个子查询,全部初始化 iii. Join 1. 对OID检索方式有用 2. 对hql检索方式没有用 b) 在hql中要使用迫切左外连接时,必须加 left join fetch 对象.关系属性 i. 如果不加fetch关键字,则hibernate不会抓取关系属性,但会遍历关系属性所对应的 ii. 不加fetch关键字时,select 要指定返回的对象,否则它要返回数组 iii. 条件:持久化类之间有关系属性映射 Hibernate级联操作对象的关系属性: 映射文件中设置: 1. Cascade a) none b) Save-update 当使用session的api对当前对象进行save,update操作时,对它的关系属性也进行save或者update c) Delete d) All = delete + save-update e) Delete-orphan 只是删除父子关系的子对象 f) All-delete-orphan 父子关系的设为此值,示,当删除一个父对象时,将这个set容器中的子对象全部删除 2. Inverse 只能在set映射时使用;它的作用是:是否根据set容器中存放的对象,产生update语句,维护关系(子)的外键属性;取值为true时,将不产生update语句。当inverse设为true时,通过父亲增儿子时,必须建立双向关系. Session的一级缓存:(相当于一系列的map容器,它是需要维护的) 1. 提高效率 2. 维护缓存中的对象和数据库中对应的记录之间进行同步 3. 当一级缓存中的对象状态(属性)发展生改变时,session在特定的时刻清理缓存: a) 清理缓存的时间点: i. Transaction.commit(); 事务提交时 ii. Session.flush(); 4. 管理session一级缓存的方法 a) Session.evict(obj)从session的一级缓存中移出一个对象 b) Session.clear() 将一级缓存中的所有对象全部清空 c) Session.close() 关闭一个session 对象的状态和对象的生命周期: 持久化类的对象,在hibernate应用中可以处于三种状态(根据对象和session之间的关系进行划分): 1. 临时态,瞬态:特点: a) 在数据库中没有记录和它对应 b) 和session没有任何关系 c) New 出来的对象,都处于临时态 2. 持久态:特点: a) 处于session的一级缓存中 b) 数据库中有一条记录和它对应 c) Session会在特定的时刻(清理缓存时)维护这个对象和数据库中的记录进行同步 d) 在同一个session的缓存中,具有相同OID的持久态对象,只有一个(同一个session的一缓存中,不可能同时有两个OID相同的同一个持久化类的对象存在) 3. 游离态,脱管 a) 不在一级缓存之中 b) 数据库可能有记录和它对应,也可能没有记录和它对应 c) 从一个持久态对象转化过来的,从session的一级缓存中出来的,因为调用了session的一些方法,产生了这种对象(session.close()) SessionFctory: Hibernate映射一对多关系: public class Dept implements java.io.Serializable { // Fields private Integer deptid; private String deptname; private Integer deptnum; private Integer actNum; private Date cdate; private Set emps = new HashSet(0) ; //getter/setter方法 略… } 映射文件: <hibernate-mapping> hibernate-mapping> Hibernate映射多对一: public class Emp implements java.io.Serializable { private Integer empid; private Dept dept; private String empname; //getter/setter方法略 } <hibernate-mapping> hibernate-mapping> Hibernate映射一对一(通过主键实现一对一的关系) //主PO对象(一个员工对个应一个身份证) public class Employees implements Serializable{ private Integer empid; private String name; private String sex; private Date birthday; private Double salary; //关系属性: private Idcard idcard; } <hibernate-mapping package ="org.wllt.www.po"> … 属性映射略 hibernate-mapping> //子PO对象 public class Idcard { private Integer empid; private String cardno; private String addr; private String fzjg; private Date enddate; //关系属性 private Employees emp; } <hibernate-mapping package="org.wllt.www.po3"> emp hibernate-mapping> Hibernate映射一对一(通过外键实现一对一的关系) 子引用主的主键做外键,这个外键建立了unique约束、not-null约束 //主对象: public class Dept implements java.io.Serializable { private Integer deptid; private String deptname; private Integer deptnum; private Integer actNum; private Date cdate; //关系属性 private Phonenote phonenote; } <hibernate-mapping> <-- …property 映射略 --> hibernate-mapping> 子对象 public class Phonenote implements java.io.Serializable { // Fields private Integer phonid; private Dept dept; private String phonecode; } <hibernate-mapping> hibernate-mapping> Hibernate映射多对多(两个一对多实现多对多) :材料和产品多对多,在数据库中有中间即产品材料用来存放两个之间的关系 Java类:材料PO,产品PO,中间PO,中间PO的复合主键类(由于是两个一对多形成的多对多,所以,这里只讲一个一对多,另一个是相同的映射方法) //产品类: public class Product { private Integer cpbh; private String cpmc; private String gg; private String sh; private String nbxh; private String txm; private String bzfs; private Set proMals = new HashSet(0); } <hibernate-mapping package="org.wllt.www.po"> <-- property 映射略 --> hibernate-mapping> 中间PO public class ProMal { private ProMalId id; } 复合主键类: public class ProMalId implements Serializable{ private Product product; private Clzb clzb; } <hibernate-mapping package="org.wllt.www.po"> hibernate-mapping> Hibernate映射多对多(两个PO类直接实现多对多) :材料和产品多对多,在数据库中有中间即产品材料用来存放两个之间的关系 Java类:材料PO,产品PO,这两个PO分别包含一个set容器, 相互放对方的对象,没有中间PO, 程序员因为得不到中间PO对象,所以不能直接操作数据库的中间。中间中的记录的维护工作,只能交给hibernate来处理,这时,set容器的inverse属性必须设为false 主PO: public class Users implements java.io.Serializable { private Integer uerid; private String name; private String passwd; private Set roles = new HashSet(0); } <hibernate-mapping> <-- property的映射略 --> hibernate-mapping>
jdbc: 1.数据库连接的方式: ODBC:开放式数据库连接。 C语言实现的,提供语言和(基于SQL的)数据库进行交互的“一致性”的接口 JDBC:java版本的ODBC JDBC连接数据库的步骤: 1.注册驱动(加载驱动): 注册的方式: 1.使用类加载器(使用反射的方式) Class.forName(driverName); 2.实例化Driver Driver driver = new oracle.jdbc.driver.OracleDriver(); DriverManager.registerDriver(driver); 3.加虚拟机参数jdbc.drivers -Djdbc.drivers=oracle.jdbc.driver.OracleDriver 4.从Jdk6.0以后要求,JDBC 4.0 Drivers 必须包括 META-INF/services/java.sql.Driver 文件,有了这个文件以后不需要在显示的使用Class.forName来进行驱动的注册 Oracle数据库进行连接的时候,使用的驱动类: 1.oracle.jdbc.driver.OracleDriver 2.oracle.jdbc.OracleDriver 2.建立连接 连接方式: 1.DriverManager(中的getConnection其实也是调用的Driver.connect方法) getConnection(url);//没有用户名密码 //将用户名密码存放在java.util.Properties对象中 getConnection(url,properties); getConnection(url,user,passwd); 2.直接调用Driver.connect方法执行 Driver d = new DriverClass(); d.connect(url,properties); 3.创建Statement: Statement: 1.创建时不需要传递sql语句,但是执行时需要传递sql语句 2.如果涉及到动态参数的传递,必须使用字符串拼接 PreparedStatement: 1.创建时就需要传递sql语句,执行的时候不需要传递sql语句 2.如果涉及到动态参数的传递,可以使用字符串拼接,也可以使用?占位的形式 给?号传值使用的是 pstmt.setType(index,value); index从1开始 3.提供预编译的功能,某种程度上可以避免sql注入的问题 4.提前做语法检查,在给?赋值的过程中要求数据类型一定要匹配,这样在某种程度上可以避免因为数据类型不匹配而发生的异常 CallableStatement:主要用来执行pl/sql的一些过程,函数等。 1.写一条恒成立的select语句,无论你输入的条件是什么,总是能讲中的所有数据输出 select id,last_name from s_emp where '1' ='1'; where 1=1; findByOption(Integer age,String province,String gender){ String sql = select * from s_emp where 1=1; if(age!=null){ sql + "and age < age"; } if(province!=null){ sql + "and province=province"; } if(gender!=null){ sql + "and gender = gender"; } } 4.执行sql语句: execute:返回boolean类型的值,代是否有结果集返回(如果执行select操作,是有ResultSet的,返回值为true) executeUpdate:返回int类型的值,代的是,操作执行完成后,受影响的数据库的行计数(针对于insert,update,delete) executeQuery:返回的是ResultSet ResultSet:类似于指针或者游标的东西,里边保存的不是所有的结果,而是指向结果集的正上方。所以如果一旦连接关闭那么ResultSet将取不到值 5.处理结果 如果有结果集,处理结果集 ResultSet next(),每执行一次,向下移动一次,如果有值,返回true,如果没值返回false while(rs.next()){ rs.getType(index/columnName); 如果传的是index,那么索引是从1开始的。 select id,last_name from s_emp; 那么1代的就是id,依次类推 } 6.关闭资源 先开的后关 D:\oraclexe\app\oracle\product\10.2.0\server\jdbc\lib\ojdbc14.jar linux下启动数据库监听的命令: lsnrctl start; "select id from s_emp where name = '"+name+"'"; table s_user( id , name, age) class User{ } //分别使用Statement对象和PreparedStatement对象实现 public class JDBCTest{ //查找s_user中所有的数据,并且返回他们的集合 public Collection findAll(){ } //按照名字进行删除 public int deleteUser(String name){ } //将user对象的信息更新到数据中 public int updateUser(User user){ } //讲User对象保存到数据库中 public void insertUser(User user){ } } JDBC:本身自动帮我做事务管理的操作 AutoCommit = true; Connection.setAutoCommit(false); 正常: conn.commit(); 异常: conn.rollback(); JDBC批处理: addBatch executeBatch Statement PreparedStatement Statement{ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 String sql .... insert delete update executeUpdate select ----- Result executeQuery 4.如果有结果集处理结果集 5.资源关闭 } Statement: update/delete/insert: stmtExecute(String sql){ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 stmt.execute(sql); 4.资源关闭 } Select: stmtQuery(String sql,ResultHander handler){ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 ResultSet set = executeQuery 4.如果有结果集处理结果集 handler!=null handler.handler(set); 5.资源关闭 } 结果集处理的规则: ResultHandler{ handler(ResultSet rs); } PreparedStatement update/delete/insert: pstmtExecute(String sql,PstmtSetter setter){ 1.获取连接 getConnection(); 2.创建PreparedStatement conn.prepareStatement(sql); if(setter!=null){ setter.setter(pstmt); } 3.执行sql语句 pstmt.execute(sql); 4.资源关闭 } ?设值的标准: PstmtSetter{ setter(PreparedStatement pstmt); } Select: stmtQuery(String sql,PstmtSetter setter,ResultHander handler){ 1.获取连接 getConnection(); 2.创建PreparedStatement conn.prepareStatement(); setter!=null setter.setter(pstmt); 3.执行sql语句 ResultSet set = executeQuery 4.如果有结果集处理结果集 handler!=null handler.handler(set); 5.资源关闭 } 结果集处理的规则: ResultHandler{ handler(ResultSet rs); } 现层 业务逻辑层 持久层 java中的对象分为: 1.域对象:主要作为信息的载体 2.行为对象:注重操作 Register(User user){ } insert(User user){ String sql = "insert into s_user( user.getId()+user.getName().......)"; } insert(User user){ save(user); } ORM Object Relational Class-Object 名字 名 属性 字段(列) object 记录 User s_User id id name name passwd passwd insert into s_user(id,name,passwd) values(?,?,?); Hibernate:ORM的中间件,或者说是实现了ORM的一个框架,对JDBC做了轻量级的封装。 ORM:使用数据信息来描述对象和数据库之间的关系,并且能够自动实现java中持久化对象到关系型数据库中的映射 脏检查:自动对缓存中的数据进行检查,并且选择在合适的时机和数据库之间进行交互,以保持数据的一致性 延迟加载:从数据库中还原对象的时候,不会立即对对象进行初始化,而是等到用到的时候才会进行初始化 Core: POJO hibernate.cfg.xml .hbm.xml Session: 1.轻量级的,创建和销毁不需要消耗很大的资源 2.非线程安全的 3.hibernate的一级缓存 4.介于Connection和Transaction之间的一个对象 5.hibernate中用来做持久化操作的 SessionFactory 1.重量级的,创建和销毁需要消耗很大的资源,不建议频繁创建和销毁 2.线程安全的,一个数据库对应一个Sessionfactory(一般一个应用程序对应一个SessionFactory就够了) 3.是一个很大的缓存,本身维护了一个可配置的二级缓存 4.用来构建Session对象 Configuration 1.启动和配置Hibernate 2.读取hibernate的配置文件和映射文件 3.构建SessionFactory对象 Transaction 1.事务管理对象 Query 1.查询对象,HQL Criteria 1.hibernate提供的更面向对象的一种查询方式。 准备工作: 1.java中的POJO对象存在 2.数据库,得存在 3.hibernate的配置文件(hibernate.cfg.xml)得存在 4.POJO.hbm.xml文件存在 5.hibernate的jar包以及数据库的驱动包存在 Hibernate的编程: 1.构建Configuration对象读取配置文件 2.读取映射文件 3.构建SessionFactory对象 4.构建Session对象 5.开启事务 6.持久化操作 7.事务的提交(正常提交,不正常回滚) 8.关闭资源 主键增长策略: 1.increment:自动增长 select max(id) from table; 找到最大值之后+1赋给要持久化的对象 2.assigned:指派 hibernate不在自动生成主键值,需要你在插入时自己指明 3.hilo:高低值算法,由数据提供高值,程序提供低值 value = hi*(max_lo+1)+lo 4.sequences Cat: cid name color weight age --------------------------- 1.每个人都有一个地址 person{ id name } Address{ country province city street } table: id name country province city street Component:数据库中采用一张的设计,java中采用两个类的设计 ----------------------------------- Employee: id name salary award amount table id name salary award formula: ---------------------------- 关系模型: 多对一: 订单和客户之间的关系 Order{ id amount customer } Customer{ id name } many-to-one:标签中对于cascade的取值delete,delete-orphan,all-delete-orphan(只用unique属性值不为true不能出现)慎用 cascade:级联属性 none:不做任何级联操作 save-update:对当前对象执行save,update, saveOrupdate,会级联操作和它相关联的对象 delete:在删除当前对象的时候,级联删除和他相关联的对象 all: save-update+delete delete-orphan:解除关联关系时,删除和当前对象失去关联的对象 all-delete-orphan:all+delete-orphan 单向的一对多的关系,在进行关联关系的操作时,会执行不必要的update语句,所以,一般情况下,我们不会做单向一对多的映射。 inverse="true":让其中一方放弃对关联关系的维护 一般在做双向多对一(一对多)关联关系映射的时候,一般会设置让一的一方放弃对关联关系的维护,以减少不必要的更新语句 一对一: 基于外键的一对一 Wife Husband id id name name h_id references Husband(id) unique 基于主键的一对一 Wife Husband id references Husband(id) id name name create table Husband( id number primary key, name varchar2(15) ); create table Wife( id number primary key references husband(id), name varchar2(15) ); 多对多: Teacher Student id id name name 桥:s_t s_id t_id ------------------------------ 操作持久化对象: Hibernate中对象的三种状态: Transient(瞬态): 1.由new关键字创建 2.没有和Session进行关联的 3.数据库中没有对应的记录存在 4.操作不会影响数据库中的数据 Persistent(持久态): 1.和Session之间有关联 2.在数据库中有对应记录存在,并且有持久化标识 3.对持久对象的更动,会对数据库中的数据产生影响。(自动脏检查机制) Detached(托管状态): 1.和Session失去关联 2.数据库中有对应记录存在 3.对托管对象的更动,在托管期间不会影响数据库,但是将托管状态重新和数据库进行关联的时候会将托管对象重新变为持久态,那么在托管期间发生的更动也会被更新到数据库中 get()/load():从数据库中还原数据 get: 1.先从缓存中进行查找,如果找到就直接返回 2.如果找不到,get()会立即发送sql语句到数据库中查找数据,如果找到就返回,如果找不到返回null; load:(使用延迟加载策略) 1.load()方法默认要加载的对象一定存在,所以很放心的使用代理对象,等到用到的时候从缓存中查找数据,如果找到,就返回,找不到发送sql语句到数据库中查找,如果数据库中没有对应记录存在,抛ObjectNotFoundException Hibernate中的查询: 1.OID检索: get load 2.导航对象图查询: Customer ---- Order之间有对应关系 通过检索到Customer以后,想获取和Customer相关的对象,可以使用 cus.getOrders(); 3.HQL: Query sql: select name from t_cus; hql: select name from hiber.many2one.Customer query.list(); 直接发送一条select语句去中查找所有的属性 query.iterate(); 先发送一条select语句从中查找所有的id,然后根据id从缓存中进行查找,找到就返回,找不到再发送sql语句按id从数据库中进行查找,所以可能会产生N+1的问题 Customer order select from customer order where customer.id=order.c_id; 4.QBC(Query By Criteria) Criteria Restrictions Order Projections QBE(Query By Example) 5.sql A B 总额 《 4000 - 100 1900 2100 900 Session默认在遇到以下情况的时候会flush: 1.事务提交的时候 2.某些查询操作执行的时候(不是所有的查询) 3.当应用程序显示的调用session.flush操作的时候 悲观锁: LockMode LockMode.UPGRADE:借助于数据库的 select ... for update; 那么事务一定会等到上一个获取了锁的事务commit之后才执行,如果上一个事务一直不提交,那么它就一直等下去 LockMode.UPGRADE_NOWAIT: select ... for update nowait; nowait就是不等待,一旦在操作过程中发现要操作的数据被加了锁,那么直接抛 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源 乐观锁: 版本控制(version) 时间戳(timestamp)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧