总的包图:
@DocumentId//嵌入和关联实体映射
这个很重要,但主体与组件的关联错误时,往往是这个没有配置
@IndexedEmbedded(depth=*)设置允许关联的层次,也要本身的关联对象>=1才可以使用两层关联,如下:
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( CarOrder.class ).get();
org.apache.lucene.search.Query query = qb.keyword().onFields("salesman.address.city").matching("天涯").createQuery();
1.anntation开始时
2.加入二级查询和查询缓存时
3.search关联实体和组件映射
Salesman.java:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Indexed(index = "indexes/salesman")//嵌入和关联实体映射
@Table(name = "salesman")
public class Salesman implements java.io.Serializable
{
@Id
@GeneratedValue(generator = "mysqlIncrement")
@GenericGenerator(name = "mysqlIncrement", strategy = "increment")
@DocumentId//嵌入和关联实体映射
private long sid;
@Column
@Field(name="SalesmanName",index=Index.TOKENIZED,store=Store.NO)//嵌入和关联实体映射
private String salesName;
@OneToOne(mappedBy="salesman",cascade=CascadeType.ALL)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Alias alias;
@OneToMany(mappedBy="salesman",cascade = CascadeType.ALL)//双向一对多
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ContainedIn
private Set<CarOrder> carOrders = new HashSet();
@ManyToMany( //双向多对多
targetEntity=basicCar.bean.BasicCar.class,
cascade = CascadeType.ALL
)
@JoinTable(
name = "carorder",
joinColumns = { @JoinColumn(name = "salesId")} ,
inverseJoinColumns={@JoinColumn(name="carId")}
)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<BasicCar> cars = new HashSet();
@Embedded //搞定映射组件
@AttributeOverrides({
@AttributeOverride(name="province", column=@Column(name="province")),
@AttributeOverride(name="city", column=@Column(name="city")),
@AttributeOverride(name="street", column=@Column(name="street")),
@AttributeOverride(name="number", column=@Column(name="number"))
})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@IndexedEmbedded(depth=1)//嵌入和关联实体映射
private Address address;
Alias.java:
@Entity
@Table(name = "alias")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Indexed(index = "indexes/alias")
public class Alias implements java.io.Serializable{
/*@Id
@GeneratedValue(generator = "mysqlIncrement")
@GenericGenerator(name = "mysqlIncrement", strategy = "increment")
private long aid;*/
@Id
@GeneratedValue(generator = "mysqlIncrement")
@GenericGenerator(name = "mysqlIncrement", strategy = "increment")
@DocumentId//嵌入和关联实体映射
private long aid;
@Column
@Field(name="aliasName",index=Index.TOKENIZED,store=Store.NO)//嵌入和关联实体映射
private String aliasName;
@Column
private Long amoney;
@Version
@Column(name="version",nullable=false,unique=true)
private int version;
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@IndexedEmbedded(depth=2)//嵌入和关联实体映射
private Salesman salesman;
CarOrder.java:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Indexed(index = "indexes/carorder")//嵌入和关联实体映射
@Table(name = "carorder1")
public class CarOrder implements java.io.Serializable {
@Id
@GeneratedValue(generator = "mysqlIncrement")
@GenericGenerator(name = "mysqlIncrement", strategy = "increment")
@DocumentId//嵌入和关联实体映射
private long cid;
@Column
@Field(name="CarOrderName",index=Index.TOKENIZED,store=Store.NO)//嵌入和关联实体映射
private String carname;
@ManyToOne
@JoinColumn(name = "salesId")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@IndexedEmbedded(depth=2)//嵌入和关联实体映射
private Salesman salesman;
BasicCar.java:
@Entity
@Table(name="basiccar")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Indexed(index = "indexes/basiccar")
public class BasicCar implements java.io.Serializable{
@Id
@GeneratedValue(generator="mysqlIncrement")
@GenericGenerator(name="mysqlIncrement", strategy="increment")
@DocumentId//一定要有,否则:org.hibernate.search.SearchException: No document id in: basicCar.bean.BasicCar
private long id;
@Column(name = "name")
@Field(name="BaiscCarName",index=Index.TOKENIZED,store=Store.YES)
private String name;
@Column(name = "factory" , length=50)
private String factory;
@Column(name = "date")
@Temporal(TemporalType.DATE)
@Basic(fetch=FetchType.LAZY)
private Date date;
@ManyToMany(
mappedBy="cars",
targetEntity=basicCar.bean.Salesman.class,
cascade = {CascadeType.PERSIST,CascadeType.MERGE}
)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@IndexedEmbedded(depth=2)//嵌入和关联实体映射
private Set<Salesman> salesmans = new HashSet();
Address.java:
@Embeddable
public class Address implements java.io.Serializable {
@Column
private String province;
@Field(name="city",index=Index.TOKENIZED)//嵌入和关联实体映射
@Column
private String city;
@Column
private String street;
@Column
private String number;
Test.java:
/*javax.persistence.NameQueries(
@javax.persistence.NamedQuery(name="easyQuery", query="from Basiccar"))*/
package basicCar;
import java.sql.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import basicCar.bean.Address;
import basicCar.bean.BasicCar;
import basicCar.bean.CarOrder;
import basicCar.bean.Salesman;
public class Test{
Configuration cfg;
SessionFactory sf;
Session session;
public static void main(String[] args)throws Exception {
Test test = new Test();
test.doConfiguration();
// test.openSession();
//test.saveEntity();
test.queryEntity();
// test.closeSession();
System.out.println("end");
}
void doConfiguration() {
// new a configuration and read the configuration from the given path
cfg = new Configuration();
cfg.configure();
sf = cfg.buildSessionFactory();
}
// save a BasicCar in database
void saveEntity() {
// begin a transaction to save
session = sf.openSession();
Transaction tx1 = session.beginTransaction();
/*BasicCar bc = new BasicCar();
bc.setFactory("dddddk");
bc.setDate(Date.valueOf("1999-02-02"));
bc.setName("hello 3456");
session.save(bc);*/
Salesman sa1 = new Salesman("中国");
Address ad1 = new Address("海南","天涯","河口","211");
CarOrder ca1 = new CarOrder("天空 很美");
CarOrder ca2 = new CarOrder("天空 很蓝");
CarOrder ca3 = new CarOrder("天空 很灰");
sa1.setAddress(ad1);
Set carorders = new HashSet();
carorders.add(ca1);
carorders.add(ca2);
carorders.add(ca3);
ca1.setSalesman(sa1);
ca2.setSalesman(sa1);
ca3.setSalesman(sa1);
sa1.setCarOrders(carorders);
session.save(sa1);
session.save(ca1);
session.save(ca2);
session.save(ca3);
tx1.commit();
session.close();
}
void queryEntity() throws Exception{
session = sf.openSession();
FullTextSession fullTextSession=Search.getFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
/*QueryParser parser=new QueryParser("carName", new StandardAnalyzer());
org.apache.lucene.search.Query luceneQuery=parser.parse("carName: iris");
Query hibernateQuery=fullTextSession.createFullTextQuery(luceneQuery, BasicCar.class);
List list=hibernateQuery.list();
BasicCar bc3 = (BasicCar) list.get(0);
System.out.println("name for the first selectedcar is: "
+ bc3.getName());*/
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( CarOrder.class ).get();
org.apache.lucene.search.Query query = qb.keyword().onFields("salesman.address.city").matching("天涯").createQuery();
// wrap Lucene query in a org.hibernate.Query
org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(query, CarOrder.class);
// execute search
List result = hibQuery.list();
for(int i=0;i<result.size();i++)
{
CarOrder bc3 = (CarOrder) result.get(i);
System.out.println("id for the selected basiccar is:"
+bc3.getcarname());
}
tx.commit();
session.close();
}
void queryEntity2() throws Exception{
session = sf.openSession();
FullTextSession fullTextSession=Search.getFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( CarOrder.class ).get();
org.apache.lucene.search.Query query = qb.keyword().onFields("CarOrderName").matching("很美").createQuery();
org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(query, CarOrder.class);
// execute search
List result = hibQuery.list();
for(int i=0;i<result.size();i++)
{
CarOrder bc3 = (CarOrder) result.get(i);
Salesman sa1 = bc3.getSalesman();
System.out.print("id for the selected basiccar is:"
+bc3.getcarname()+" ");
System.out.print("about salesman is:"
+sa1.getSalesname()+" ");
System.out.println("address is:"
+sa1.getAddress().getCity());
}
tx.commit();
session.close();
}
}
hibernate.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">001052</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/chwa</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.search.default.directory_provider">org.hibernate.search.store.FSDirectoryProvider</property> <property name="hibernate.search.default.indexBase">D:/index</property> <!--设置安全级别--> <property name="hibernate.connection.isolation">2</property> <!-- 配置EhCache的缓存提供者 --> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider </property> <!-- 启动sessionfactory级别的Statistics统计,用于记录持久化操作 --> <property name="hibernate.generate_statistics">true</property> <!-- 设置二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- 查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property> <!-- 观看查询是输出的sql语句,知道使用和不使用二级缓存的区别--> <property name="hibernate.show_sql">true</property> <!--<property name="hibernate.search.default.directory_provider">filesystem</property> <property name="hibernate.search.default.indexBase">/var/lucene/indexes</property>--> <mapping class="basicCar.bean.Salesman"/> <mapping class="basicCar.bean.CarOrder"/> <mapping class="basicCar.bean.Alias"/> <mapping class="basicCar.bean.BasicCar"/> </session-factory></hibernate-configuration> ehcache.xml:<!--设置索引存放地址-->
<ehcache> <diskStore path="C:\\temp"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="basicCar.bean.Salesman" maxElementsInMemory="5" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="true" /> <cache name="basicCar.bean.BasicCar" maxElementsInMemory="5" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="true" /> <cache name="basicCar.bean.CarOrder" maxElementsInMemory="5" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="true" /> <cache name="basicCar.bean.Alias" maxElementsInMemory="5" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="true" /> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> <!-- Place configuration for your caches following --> <cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="50" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="60" overflowToDisk="true" /> <!-- 设置时间戳缓存的数据过期策略 ,保存每个表的最近更新时间--> <!-- 查看它的生成时间是不是最后更新时间,如果不是,则证明这个查询缓存已经过期了。 因此只要更新过一个表,涉及这个表的查询缓存就过期了--> <cache name="org.hibernate.cache.UpdateTimestampsCahe" maxElementsInMemory="5000" eternal="true" overflowToDisk="true" /> </ehcache>